train <- read.csv(file="train.csv", na.strings=c(""))
test <- read.csv(file="test.csv", na.strings=c(""))
summary(train)
                 Dates                  Category                                       Descript     
 2011-01-01 00:01:00:   185   LARCENY/THEFT :174900   GRAND THEFT FROM LOCKED AUTO         : 60022  
 2006-01-01 00:01:00:   136   OTHER OFFENSES:126182   LOST PROPERTY                        : 31729  
 2012-01-01 00:01:00:    94   NON-CRIMINAL  : 92304   BATTERY                              : 27441  
 2006-01-01 12:00:00:    63   ASSAULT       : 76876   STOLEN AUTOMOBILE                    : 26897  
 2007-06-01 00:01:00:    61   DRUG/NARCOTIC : 53971   DRIVERS LICENSE, SUSPENDED OR REVOKED: 26839  
 2006-06-01 00:01:00:    58   VEHICLE THEFT : 53781   WARRANT ARREST                       : 23754  
 (Other)            :877452   (Other)       :300035   (Other)                              :681367  
     DayOfWeek           PdDistrict                 Resolution                         Address      
 Friday   :133734   SOUTHERN  :157182   NONE             :526790   800 Block of BRYANT ST  : 26533  
 Monday   :121584   MISSION   :119908   ARREST, BOOKED   :206403   800 Block of MARKET ST  :  6581  
 Saturday :126810   NORTHERN  :105296   ARREST, CITED    : 77004   2000 Block of MISSION ST:  5097  
 Sunday   :116707   BAYVIEW   : 89431   LOCATED          : 17101   1000 Block of POTRERO AV:  4063  
 Thursday :125038   CENTRAL   : 85460   PSYCHOPATHIC CASE: 14534   900 Block of MARKET ST  :  3251  
 Tuesday  :124965   TENDERLOIN: 81809   UNFOUNDED        :  9585   0 Block of TURK ST      :  3228  
 Wednesday:129211   (Other)   :238963   (Other)          : 26632   (Other)                 :829296  
       X                Y        
 Min.   :-122.5   Min.   :37.71  
 1st Qu.:-122.4   1st Qu.:37.75  
 Median :-122.4   Median :37.78  
 Mean   :-122.4   Mean   :37.77  
 3rd Qu.:-122.4   3rd Qu.:37.78  
 Max.   :-120.5   Max.   :90.00  
                                 
library(Amelia)
Loading required package: Rcpp
## 
## Amelia II: Multiple Imputation
## (Version 1.7.4, built: 2015-12-05)
## Copyright (C) 2005-2017 James Honaker, Gary King and Matthew Blackwell
## Refer to http://gking.harvard.edu/amelia/ for more information
## 
missmap(train, main = "Missing values vs observed")

It seems that here are no missing values. Great!

# Overall structure
str(train)
'data.frame':   878049 obs. of  9 variables:
 $ Dates     : Factor w/ 389257 levels "2003-01-06 00:01:00",..: 389257 389257 389256 389255 389255 389255 389255 389255 389254 389254 ...
 $ Category  : Factor w/ 39 levels "ARSON","ASSAULT",..: 38 22 22 17 17 17 37 37 17 17 ...
 $ Descript  : Factor w/ 879 levels "ABANDONMENT OF CHILD",..: 867 811 811 405 405 407 740 740 405 405 ...
 $ DayOfWeek : Factor w/ 7 levels "Friday","Monday",..: 7 7 7 7 7 7 7 7 7 7 ...
 $ PdDistrict: Factor w/ 10 levels "BAYVIEW","CENTRAL",..: 5 5 5 5 6 3 3 1 7 2 ...
 $ Resolution: Factor w/ 17 levels "ARREST, BOOKED",..: 1 1 1 12 12 12 12 12 12 12 ...
 $ Address   : Factor w/ 23228 levels "0 Block of  HARRISON ST",..: 19791 19791 22698 4267 1844 1506 13323 18055 11385 17659 ...
 $ X         : num  -122 -122 -122 -122 -122 ...
 $ Y         : num  37.8 37.8 37.8 37.8 37.8 ...
# Get to know data types
sapply(train, class)
     Dates   Category   Descript  DayOfWeek PdDistrict Resolution    Address          X          Y 
  "factor"   "factor"   "factor"   "factor"   "factor"   "factor"   "factor"  "numeric"  "numeric" 
# summarize the class distribution
cat_percentage <- prop.table(table(train$Category)) * 100
cbind(freq=table(train$Category), percentage=cat_percentage)
                              freq   percentage
ARSON                         1513 1.723138e-01
ASSAULT                      76876 8.755320e+00
BAD CHECKS                     406 4.623888e-02
BRIBERY                        289 3.291388e-02
BURGLARY                     36755 4.185985e+00
DISORDERLY CONDUCT            4320 4.919999e-01
DRIVING UNDER THE INFLUENCE   2268 2.582999e-01
DRUG/NARCOTIC                53971 6.146696e+00
DRUNKENNESS                   4280 4.874443e-01
EMBEZZLEMENT                  1166 1.327944e-01
EXTORTION                      256 2.915555e-02
FAMILY OFFENSES                491 5.591943e-02
FORGERY/COUNTERFEITING       10609 1.208247e+00
FRAUD                        16679 1.899552e+00
GAMBLING                       146 1.662777e-02
KIDNAPPING                    2341 2.666138e-01
LARCENY/THEFT               174900 1.991916e+01
LIQUOR LAWS                   1903 2.167305e-01
LOITERING                     1225 1.395139e-01
MISSING PERSON               25989 2.959858e+00
NON-CRIMINAL                 92304 1.051240e+01
OTHER OFFENSES              126182 1.437072e+01
PORNOGRAPHY/OBSCENE MAT         22 2.505555e-03
PROSTITUTION                  7484 8.523442e-01
RECOVERED VEHICLE             3138 3.573832e-01
ROBBERY                      23000 2.619444e+00
RUNAWAY                       1946 2.216277e-01
SECONDARY CODES               9985 1.137180e+00
SEX OFFENSES FORCIBLE         4388 4.997443e-01
SEX OFFENSES NON FORCIBLE      148 1.685555e-02
STOLEN PROPERTY               4540 5.170554e-01
SUICIDE                        508 5.785554e-02
SUSPICIOUS OCC               31414 3.577705e+00
TREA                             6 6.833332e-04
TRESPASS                      7326 8.343498e-01
VANDALISM                    44725 5.093679e+00
VEHICLE THEFT                53781 6.125057e+00
WARRANTS                     42214 4.807704e+00
WEAPON LAWS                   8555 9.743192e-01
# Get top crimes
crime_categories_df <- as.data.frame(table(train$Category))
crime_categories_df[with(crime_categories_df, order(-Freq)),]
top_crimes <- head(crime_categories_df[with(crime_categories_df, order(-Freq)),], n=10)
# Create data for the graph.
x <- top_crimes$Freq
labels <- top_crimes$Var1
piepercent <- round(100*x/sum(x), 1)
# Plot the chart.
pie(x, labels = piepercent, main = "Top 10 Crimes",col = rainbow(length(x)))
legend("right", as.character(labels), cex = 0.8,
   fill = rainbow(length(x)))

We can see that larceny/theft and non-criminal takes up much of the pie, followed by non-criminal and assult. ‘Other offenses’ also accounts for a large proportion, but it contains ambiguities and lacks information.

Is there a day of week that has significantly more crimes than other days? The distribution is rather even. But Friday is surely a peak (maybe people consume more after a week’s work) while Sunday is a slump (most people stay at home).

library(ggplot2)

Attaching package: 'ggplot2'

The following object is masked from 'package:NLP':

    annotate
table(train$Category ,train$DayOfWeek)
                             
                              Friday Monday Saturday Sunday Thursday Tuesday Wednesday
  ARSON                          220    228      220    211      199     235       200
  ASSAULT                      11160  10560    11995  12082    10246   10280     10553
  BAD CHECKS                      62     66       45     20       66      76        71
  BRIBERY                         49     41       42     41       39      37        40
  BURGLARY                      6327   5262     4754   4231     5350    5374      5457
  DISORDERLY CONDUCT             541    608      624    586      644     657       660
  DRIVING UNDER THE INFLUENCE    352    263      457    442      282     251       221
  DRUG/NARCOTIC                 7420   7823     6390   6143     8454    8474      9267
  DRUNKENNESS                    622    513      833    813      496     461       542
  EMBEZZLEMENT                   211    222      137    108      165     156       167
  EXTORTION                       35     30       32     39       40      39        41
  FAMILY OFFENSES                 82     69       59     54       63      85        79
  FORGERY/COUNTERFEITING        1757   1704     1178    901     1610    1752      1707
  FRAUD                         2641   2533     2256   1874     2351    2506      2518
  GAMBLING                        35     16       21     12       20      12        30
  KIDNAPPING                     385    340      355    374      289     306       292
  LARCENY/THEFT                27104  23570    27217  24150    24415   23957     24487
  LIQUOR LAWS                    291    188      297    222      248     323       334
  LOITERING                      139    193      140    155      186     252       160
  MISSING PERSON                4663   3592     3752   3061     3680    3655      3586
  NON-CRIMINAL                 13984  12855    14007  12973    12819   12738     12928
  OTHER OFFENSES               18588  17787    17129  15457    18462   18809     19950
  PORNOGRAPHY/OBSCENE MAT          4      3        1      3        5       3         3
  PROSTITUTION                  1158    409      850    620     1547    1421      1479
  RECOVERED VEHICLE              494    530      343    307      432     517       515
  ROBBERY                       3384   3194     3428   3284     3216    3221      3273
  RUNAWAY                        344    280      268    205      305     275       269
  SECONDARY CODES               1392   1483     1462   1543     1389    1343      1373
  SEX OFFENSES FORCIBLE          621    607      662    690      585     597       626
  SEX OFFENSES NON FORCIBLE       28     23       21     16       15      23        22
  STOLEN PROPERTY                647    636      581    583      679     714       700
  SUICIDE                         72     75       73     67       89      66        66
  SUSPICIOUS OCC                4924   4447     4155   4010     4510    4517      4851
  TREA                             1      1        2      0        1       1         0
  TRESPASS                      1064   1081      983    915     1047    1114      1122
  VANDALISM                     7092   5946     7326   6602     5980    5852      5927
  VEHICLE THEFT                 8613   7412     8119   7504     7456    7263      7414
  WARRANTS                      5926   5811     5364   5281     6376    6427      7029
  WEAPON LAWS                   1302   1183     1232   1128     1282    1176      1252
g <- ggplot(train, aes(DayOfWeek))
g + geom_bar(aes(fill = Category)) + theme(legend.position="bottom")

How does criminal activities change over the years? Does it increase or decrease or stay the same?

train$Year <- substring(train$Dates, 1, 4)
train$Month <- substring(train$Dates, 6, 7)
crime_history <- head(as.vector(table(train$Month,train$Year)), -12)
crime_history
  [1] 5831 5964 6099 6758 7025 6052 5503 5800 6704 7259 6194 4713 5938 5626 7262 6988 6865 5614 5679 6439 6361
 [22] 6695 5011 4944 5669 5252 5448 5586 6426 6134 6512 5428 5426 6292 6422 6184 5896 5537 5418 5524 6177 6393
 [43] 6246 5523 5312 6183 5868 5832 5094 5093 5209 5336 6253 5984 5894 5331 5509 6733 6253 5326 5182 5284 5974
 [64] 6028 6597 5556 5631 5275 6367 7173 6371 4736 5272 5237 6580 6472 6355 4543 4960 6199 6671 6593 5581 4537
 [85] 5179 5063 4997 4890 5708 5888 6207 5758 5453 5395 5906 6098 6130 5029 5071 5123 5742 5915 5895 5056 5278
[106] 5410 5761 6209 5987 5367 5341 5618 6563 6024 5692 5481 5585 7497 6584 5992 5712 5694 5830 6615 6924 6797
[127] 5944 6103 6649 7741 6553 5044 5780 5659 6240 6549 6759 5992 5808 6147 6667 7303 6471 5391
crime_ts <- ts(crime_history, frequency=12, start=c(2003,1))
crime_ts 
      Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
2003 5831 5964 6099 6758 7025 6052 5503 5800 6704 7259 6194 4713
2004 5938 5626 7262 6988 6865 5614 5679 6439 6361 6695 5011 4944
2005 5669 5252 5448 5586 6426 6134 6512 5428 5426 6292 6422 6184
2006 5896 5537 5418 5524 6177 6393 6246 5523 5312 6183 5868 5832
2007 5094 5093 5209 5336 6253 5984 5894 5331 5509 6733 6253 5326
2008 5182 5284 5974 6028 6597 5556 5631 5275 6367 7173 6371 4736
2009 5272 5237 6580 6472 6355 4543 4960 6199 6671 6593 5581 4537
2010 5179 5063 4997 4890 5708 5888 6207 5758 5453 5395 5906 6098
2011 6130 5029 5071 5123 5742 5915 5895 5056 5278 5410 5761 6209
2012 5987 5367 5341 5618 6563 6024 5692 5481 5585 7497 6584 5992
2013 5712 5694 5830 6615 6924 6797 5944 6103 6649 7741 6553 5044
2014 5780 5659 6240 6549 6759 5992 5808 6147 6667 7303 6471 5391
plot.ts(crime_ts)

We can see that the basic trend is declining from 2004 to 2010. Then, crime rate begins to rise until 2014. But noticeably we can clearly observe the seasonality throughout the years. So it’s worthwhile to investigate the fluctuation over the months. Maybe some analysis over time-in-a-day would be helpful too. For now let’s just decompose the data.

crime_components <- decompose(crime_ts)
plot(crime_components)

It seems the trend is just what I described, roughly. The seasonal component seems really interesting.

train_incomplete <- subset(train, Year != 2015)
tb <- table(train_incomplete$Month, train_incomplete$Category)
df <- data.frame(month=as.integer(row.names(tb)), crime_freq=as.vector(tb), crime_categories=rep(colnames(tb), each=length(row.names(tb))))
# plot
ggplot(data = df, aes(x=month, y=crime_freq)) + geom_line(aes(colour=crime_categories)) + theme(legend.position="left")

# Create the data for the chart.
tb <- table(train_incomplete$Month, train_incomplete$Category)
v = rowSums(tb)
# Plot the bar chart.
plot(v,type = "o", col = "red", xlab = "Month", ylab = "Crime Frequency",
   main = "Monthly Crime")

We can see that, usually December and Feburary has the lowest crime rate (perhaps people feel too cold to leave home). June, July, August have low frequency as well. Crime activities peak in May and October. This pattern is observed by all major categories of crime. However, the data of December is significantly lower than the others. Maybe it’s because of the lack of data in 2015. I’ll get rid of the data of 2015 when necessary and adjust the previous results.

Just an example of mapping SF.

library(ggplot2)
library(ggmap)
Google Maps API Terms of Service: http://developers.google.com/maps/terms.
Please cite ggmap if you use it: see citation('ggmap') for details.
library(maptools)
Loading required package: sp
Checking rgeos availability: TRUE
library(ggthemes)
library(rgeos)
rgeos version: 0.3-23, (SVN revision 546)
 GEOS runtime version: 3.6.1-CAPI-1.10.1 r0 
 Linking to sp version: 1.2-4 
 Polygon checking: TRUE 
library(broom)
library(dplyr)

Attaching package: 'dplyr'

The following objects are masked from 'package:rgeos':

    intersect, setdiff, union

The following objects are masked from 'package:stats':

    filter, lag

The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(plyr)
---------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
---------------------------------------------------------------------------------------------------------------

Attaching package: 'plyr'

The following objects are masked from 'package:dplyr':

    arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
library(grid)
library(gridExtra)

Attaching package: 'gridExtra'

The following object is masked from 'package:dplyr':

    combine
library(reshape2)
library(scales)
plotTheme <- function(base_size = 12) {
  theme(
    text = element_text( color = "black"),
    plot.title = element_text(size = 18,colour = "black"),
    plot.subtitle = element_text(face="italic"),
    plot.caption = element_text(hjust=0),
    axis.ticks = element_blank(),
    panel.background = element_blank(),
    panel.grid.major = element_line("grey80", size = 0.1),
    panel.grid.minor = element_blank(),
    strip.background = element_rect(fill = "grey80", color = "white"),
    strip.text = element_text(size=12),
    axis.title = element_text(size=8),
    axis.text = element_text(size=8),
    axis.title.x = element_text(hjust=1),
    axis.title.y = element_text(hjust=1),
    plot.background = element_blank(),
    legend.background = element_blank(),
    legend.title = element_text(colour = "black", face = "italic"),
    legend.text = element_text(colour = "black", face = "italic"))
}
 
# And another that we will use for maps
mapTheme <- function(base_size = 12) {
  theme(
    text = element_text( color = "black"),
    plot.title = element_text(size = 18,colour = "black"),
    plot.subtitle=element_text(face="italic"),
    plot.caption=element_text(hjust=0),
    axis.ticks = element_blank(),
    panel.background = element_blank(),
    panel.grid.major = element_line("grey80", size = 0.1),
    strip.text = element_text(size=12),
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    panel.grid.minor = element_blank(),
    strip.background = element_rect(fill = "grey80", color = "white"),
    plot.background = element_blank(),
    legend.background = element_blank(),
    legend.title = element_text(colour = "black", face = "italic"),
    legend.text = element_text(colour = "black", face = "italic"))
}
 
# Define some palettes
palette_9_colors <- c("#0DA3A0","#2999A9","#458FB2","#6285BB","#7E7CC4","#9A72CD","#B768D6","#D35EDF","#F055E9")
palette_8_colors <- c("#0DA3A0","#2D97AA","#4D8CB4","#6E81BF","#8E76C9","#AF6BD4","#CF60DE","#F055E9")
palette_7_colors <- c("#2D97AA","#4D8CB4","#6E81BF","#8E76C9","#AF6BD4","#CF60DE","#F055E9")
palette_1_colors <- c("#0DA3A0")
# Read in a csv of home sale transactions directly from github.
sf <- read.csv("https://raw.githubusercontent.com/simonkassel/Visualizing_SF_home_prices_R/master/Data/SF_home_sales_demo_data.csv")
 
# We will need to consider Sale Year as a categorical variable so we convert it from a numeric variable to a factor
sf$SaleYr <- as.factor(sf$SaleYr)
# Define the URL of the zipped shapefile
URL <- "https://github.com/simonkassel/Visualizing_SF_home_prices_R/raw/master/Data/SF_neighborhoods.zip"
# Download the shapefile to your working directory and unzip it.
download.file(URL, "SF_neighborhoods.zip")
trying URL 'https://github.com/simonkassel/Visualizing_SF_home_prices_R/raw/master/Data/SF_neighborhoods.zip'
Content type 'application/zip' length 141938 bytes (138 KB)
==================================================
downloaded 138 KB
unzip("SF_neighborhoods.zip")
# Read it into R as a spatial polygons data frame & plot
neighb <- readShapePoly("SF_neighborhoods")
use rgdal::readOGR or sf::st_read
plot(neighb)

# Define the bounding box
bbox <- neighb@bbox
# Manipulate these values slightly so that we get some padding on our basemap between the edge of the data and the edge of the map
sf_bbox <- c(left = bbox[1, 1] - .01, bottom = bbox[2, 1] - .005, 
             right = bbox[1, 2] + .01, top = bbox[2, 2] + .005)
# Download the basemap
basemap <- get_stamenmap(
  bbox = sf_bbox,
  zoom = 13,
  maptype = "toner-lite")
Map from URL : http://tile.stamen.com/toner-lite/13/1307/3165.png
Map from URL : http://tile.stamen.com/toner-lite/13/1308/3165.png
Map from URL : http://tile.stamen.com/toner-lite/13/1309/3165.png
Map from URL : http://tile.stamen.com/toner-lite/13/1310/3165.png
Map from URL : http://tile.stamen.com/toner-lite/13/1311/3165.png
Map from URL : http://tile.stamen.com/toner-lite/13/1307/3166.png
Map from URL : http://tile.stamen.com/toner-lite/13/1308/3166.png
Map from URL : http://tile.stamen.com/toner-lite/13/1309/3166.png
Map from URL : http://tile.stamen.com/toner-lite/13/1310/3166.png
Map from URL : http://tile.stamen.com/toner-lite/13/1311/3166.png
Map from URL : http://tile.stamen.com/toner-lite/13/1307/3167.png
Map from URL : http://tile.stamen.com/toner-lite/13/1308/3167.png
Map from URL : http://tile.stamen.com/toner-lite/13/1309/3167.png
Map from URL : http://tile.stamen.com/toner-lite/13/1310/3167.png
Map from URL : http://tile.stamen.com/toner-lite/13/1311/3167.png
Map from URL : http://tile.stamen.com/toner-lite/13/1307/3168.png
Map from URL : http://tile.stamen.com/toner-lite/13/1308/3168.png
Map from URL : http://tile.stamen.com/toner-lite/13/1309/3168.png
Map from URL : http://tile.stamen.com/toner-lite/13/1310/3168.png
Map from URL : http://tile.stamen.com/toner-lite/13/1311/3168.png
# # Map it
# bmMap <- ggmap(basemap) + mapTheme() + 
#   labs(title="San Francisco basemap")
# bmMap
# Define the bounding box
bbox <- neighb@bbox
 
# Manipulate these values slightly so that we get some padding on our basemap between the edge of the data and the edge of the map
sf_bbox <- c(left = bbox[1, 1] - .01, bottom = bbox[2, 1] - .005, 
             right = bbox[1, 2] + .01, top = bbox[2, 2] + .005)
# Download the basemap
basemap <- get_stamenmap(
  bbox = sf_bbox,
  zoom = 13,
  maptype = "toner-lite")
 
# # Map it
# bmMap <- ggmap(basemap) + mapTheme() + 
#   labs(title="San Francisco basemap")
# bmMap
# 
# prices_mapped_by_year <- ggmap(basemap) + 
#   geom_point(data = sf, aes(x = long, y = lat, color = SalePrice), 
#              size = .25, alpha = 0.6) +
#   facet_wrap(~SaleYr, scales = "fixed", ncol = 4) +
#   coord_map() +
#   mapTheme() + theme(legend.position = c(.85, .25)) +
#   scale_color_gradientn("Sale Price", 
#                         colors = palette_8_colors,
#                         labels = scales::dollar_format(prefix = "$")) +
#   labs(title="Distribution of San Francisco home prices",
#        subtitle="Nominal prices (2009 - 2015)",
#        caption="Source: San Francisco Office of the Assessor-Recorder\n@KenSteif & @SimonKassel")
# prices_mapped_by_year
train[, c("X", "Y", "Year", "Category")]
crime_location <- data.frame( train[, c("X", "Y", "Year", "Category")] )
crime_location
# Manipulate these values slightly so that we get some padding on our basemap between the edge of the data and the edge of the map
sf_bbox <- c(left = bbox[1, 1] - .01, bottom = bbox[2, 1] - .005, 
         right = bbox[1, 2] + .01, top = bbox[2, 2] + .005)
# Download the basemap
basemap <- get_stamenmap(
  bbox = sf_bbox,
  zoom = 13,
  maptype = "toner-lite")
 
# Map it
bmMap <- ggmap(basemap) + mapTheme() + 
  labs(title="San Francisco Crime Map")
bmMap + geom_point(data=crime_location, aes(x=X, y=Y, color=Category), size=0.7, alpha=0.3) + theme(legend.position = "right")

top_crime_map <- crime_location[crime_location$Category %in% as.vector(top_crimes$Var1),]
bmMapTop <- ggmap(basemap) + mapTheme() + 
  labs(title="San Francisco Top Crime Map")
bmMapTop + geom_point(data=top_crime_map, aes(x=X, y=Y, color=Category), size=0.7, alpha=0.3) + theme(legend.position = "right")

Although this map is beautiful, it provides us with too much information to be insightful. To get more out of this visualisation, we need to limit the categories to those most ‘popular’ crimes, or we need to regroup the crime categories.

# Map it
bmMap <- ggmap(basemap) + mapTheme() + 
  labs(title="San Francisco basemap")
prices_mapped_by_year <- ggmap(basemap) + 
  geom_point(data = top_crime_map, aes(x = X, y = Y, color = Category), 
             size = .25, alpha = 0.6) +
  facet_wrap(~Year, scales = "fixed", ncol = 4) +
  coord_map() +
  mapTheme() + theme(legend.position = "right") +
  labs(title="Top 10 Crimes in San Francisco",
       subtitle="2003 - 2015")
prices_mapped_by_year

Ok anyways… Thanks to Kelvin, I noticed there is a very strong correlation between the Descrition column and the Category column. Some text mining is needed though.

#train$Descript
library(tm)
library(wordcloud)
descript <- removeNumbers(removePunctuation(tolower(as.vector(train$Descript)))) 
descript <- removeWords(descript, stopwords("en"))
descript_corpus <- Corpus(VectorSource(train$Descript))
descript_corpus = tm_map(descript_corpus, content_transformer(tolower))
descript_corpus = tm_map(descript_corpus, removeNumbers)
descript_corpus = tm_map(descript_corpus, removePunctuation)
descript_corpus = tm_map(descript_corpus, removeWords, c("the", "and"))
descript_corpus =  tm_map(descript_corpus, stripWhitespace)
descript_dtm <- DocumentTermMatrix(descript_corpus)
descript_dtm <- removeSparseTerms(descript_dtm, 0.975)
findFreqTerms(descript_dtm, 100)
 [1] "arrest"     "warrant"    "traffic"    "violation"  "auto"       "from"       "grand"      "locked"    
 [9] "theft"      "automobile" "stolen"     "petty"      "malicious"  "mischief"   "vandalism"  "property"  
[17] "robbery"    "with"       "lost"       "vehicle"    "suspicious" "aided"      "case"       "drivers"   
[25] "license"    "revoked"    "suspended"  "burglary"   "entry"      "possession" "battery"    "occurrence"
raw_freq = data.frame(sort(colSums(as.matrix(descript_dtm)), decreasing=TRUE))
raw_freq
dim(raw_freq)
[1] 32  1
freq_words <- rownames(raw_freq)
freq_words
 [1] "theft"      "from"       "grand"      "auto"       "property"   "locked"     "petty"      "possession"
 [9] "stolen"     "violation"  "malicious"  "mischief"   "arrest"     "with"       "license"    "entry"     
[17] "vandalism"  "battery"    "lost"       "burglary"   "case"       "aided"      "vehicle"    "drivers"   
[25] "automobile" "revoked"    "suspended"  "suspicious" "warrant"    "robbery"    "occurrence" "traffic"   
wordcloud(rownames(raw_freq), raw_freq[,1], max.words=100, colors=brewer.pal(1, "Dark2"))
minimal value for n is 3, returning requested palette with 3 different levels

descript_dtm_tfidf <- DocumentTermMatrix(descript_corpus, control = list(weighting = weightTfIdf))
descript_dtm_tfidf = removeSparseTerms(descript_dtm_tfidf, 0.975)
freq = data.frame(sort(colSums(as.matrix(descript_dtm_tfidf)), decreasing=TRUE))
freq
freq_words <- c(freq_words, rownames(freq))
freq_words <- unique(freq_words)
freq_words
 [1] "theft"      "from"       "grand"      "auto"       "property"   "locked"     "petty"      "possession"
 [9] "stolen"     "violation"  "malicious"  "mischief"   "arrest"     "with"       "license"    "entry"     
[17] "vandalism"  "battery"    "lost"       "burglary"   "case"       "aided"      "vehicle"    "drivers"   
[25] "automobile" "revoked"    "suspended"  "suspicious" "warrant"    "robbery"    "occurrence" "traffic"   
wordcloud(rownames(freq), freq[,1], max.words=100, colors=brewer.pal(1, "Dark2"))
minimal value for n is 3, returning requested palette with 3 different levels

Ok, let’s try to search for some keywords in the descript column that matches the category column.

unique_cat <- unique(train$Category)
x <- ""
for(cat in unique(train$Category)) {
  x <- paste(x, cat, sep="|")
}
x <- tolower(substring(x,2)) 
match_count_table <- table(grepl(x, tolower(train$Descript)))
match_count_table

 FALSE   TRUE 
704738 173311 
prop.table(match_count_table)

    FALSE      TRUE 
0.8026181 0.1973819 

So about 20% of the DESCRIPT contains the CATEGORY keywords. There is a rather strong correlation indeed. This is definitely going to be a feature. How about the holidays? Let’s get some data about the public holiday in San Francisco!!!

regular_day <- train
train$Holiday <- "Regular"
# Holidays 
new_year <- regular_day[grepl("[0-9]{4}-01-01", regular_day$Dates),]
train$Holiday[grepl("[0-9]{4}-01-01", train$Dates)] <- "NewYear"
regular_day <- regular_day[!grepl("[0-9]{4}-01-01", regular_day$Dates),]
#Valentine
valentine <- regular_day[grepl("[0-9]{4}-02-14", regular_day$Dates),]
train$Holiday[grepl("[0-9]{4}-02-14", train$Dates)] <- "Valentine"
regular_day <- regular_day[!grepl("[0-9]{4}-02-14", regular_day$Dates),]
#MLK <- # Third Monday in January
#presidents_day <- # Third Monday in Febrary
#easter <- # Arr
#memorial_day <- # Last Monday in May
independence_day <- regular_day[grepl("[0-9]{4}-07-04", regular_day$Dates),]
train$Holiday[grepl("[0-9]{4}-07-04", train$Dates)] <- "Independence"
regular_day <- regular_day[!grepl("[0-9]{4}-07-04", regular_day$Dates),]
#labor_day <- # First Monday in September 
#columbus_day <- # Second Monday in October
veterans_day <- regular_day[grepl("[0-9]{4}-11-11", regular_day$Dates),]
train$Holiday[grepl("[0-9]{4}-11-11", train$Dates)] <- "Veterans"
regular_day <- regular_day[!grepl("[0-9]{4}-11-11", regular_day$Dates),]
#thanks_giving <- #  Fourth Thursday in November
christmas <- regular_day[grepl("[0-9]{4}-12-25", regular_day$Dates),]
train$Holiday[grepl("[0-9]{4}-12-25", train$Dates)] <- "Christmas"
regular_day <- regular_day[!grepl("[0-9]{4}-12-25", regular_day$Dates),]
library(ggplot2)

Attaching package: 'ggplot2'

The following object is masked from 'package:NLP':

    annotate
new_year_top_crime <- new_year[new_year$Category %in% as.vector(top_crimes$Var1),]
g <- ggplot(new_year_top_crime, aes(Year))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("New Year Crime")

ind_top_crime <- independence_day[independence_day$Category %in% as.vector(top_crimes$Var1),]
g <- ggplot(ind_top_crime, aes(Year))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Independence Day Crime")

veterans_top_crime <- veterans_day[veterans_day$Category %in% as.vector(top_crimes$Var1),]
g <- ggplot(veterans_top_crime, aes(Year))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Veterans Day Crime")

christmas_top_crime <- christmas[christmas$Category %in% as.vector(top_crimes$Var1),]
g <- ggplot(christmas_top_crime, aes(Year))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Christmas Crime")

Time to do some averaging…

library(matrixStats)
new_year_avg <- colMedians(table(new_year_top_crime$Year, droplevels(new_year_top_crime$Category))) 
valentine_top_crime <- valentine[valentine$Category %in% as.vector(top_crimes$Var1),]
valentine_avg <- colMedians(table(valentine_top_crime$Year, droplevels(valentine_top_crime$Category))) 
ind_day_avg <- colMedians(table(ind_top_crime$Year, droplevels(ind_top_crime$Category)))
veterans_avg <- colMedians(table(veterans_top_crime$Year, droplevels(veterans_top_crime$Category)))
christmas_avg <- colMedians(table(christmas_top_crime$Year, droplevels(christmas_top_crime$Category)))
reg_day_top_crime <- regular_day[regular_day$Category %in% as.vector(top_crimes$Var1),]
reg_day_top_crime$DateOnly <- substring(reg_day_top_crime$Dates, 1, 10)
#reg_day_top_crime$DateOnly
reg_day_avg <- colMedians(table(reg_day_top_crime$DateOnly, droplevels(reg_day_top_crime$Category)))
#reg_day_avg
holiday_comparison_df <- data.frame(NewYear=new_year_avg, Valentine = valentine_avg, Ind=ind_day_avg, Veterans=veterans_avg, Christmas=christmas_avg, Regular=reg_day_avg)
row.names(holiday_comparison_df) <- sort(top_crimes$Var1)
holiday_comparison_df
par(xpd=TRUE)
barplot(as.matrix(holiday_comparison_df), main="Crimes in Special Days", col=rainbow(nrow(holiday_comparison_df)), xlab="Special Days", bty='L')
legend("topright",
       legend = sort(top_crimes$Var1), 
       fill = rainbow(nrow(holiday_comparison_df)), cex=0.4)

Let’s see how the plot varies throughout the 24 hours in a day:

crime_time_df <- data.frame(Time=as.POSIXct(substring(train$Dates,12), format="%H:%M:%S"), Category=train$Category)
#ggplot(data=crime_time_df, aes(x=crime_time_df$Time, y=)) + geom_point()

Let’s see if weekends have more crimes than weekdays.

library(ggplot2)
wkday <- train
wkday$Week <- "Weekday"
wkday[wkday$DayOfWeek == "Saturday" | wkday$DayOfWeek == "Sunday",]$Week <- "Weekend"
wkday_df <- (data.frame(Week=wkday$Week, Category=wkday$Category))
wkday_df
g <- ggplot(wkday_df, aes(Week))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Weekday vs. Weekend") + theme(axis.text.x = element_text(angle=90,hjust=1))

wkday_top_crime <- wkday
wk_table <- table(wkday_top_crime$Week)
#wkday_result <- data.frame(Weekday=table(wkday_top_crime$Category, wkday_top_crime$Week)[,1]/wk_table["Weekday"],
#                          Weekend=table(wkday_top_crime$Category, wkday_top_crime$Week)[,2]/wk_table["Weekend"])
wkday_result <- data.frame(Weekday=table(wkday_top_crime$Category, wkday_top_crime$Week)[,1]/5,
                           Weekend=table(wkday_top_crime$Category, wkday_top_crime$Week)[,2]/2)
     
wkday_result
g + theme(legend.position="right")
par(xpd=TRUE)

barplot(as.matrix(wkday_result), main="Weekdays vs. Weekends", col=rainbow(nrow(wkday_result)), xlab="Day of Week", bty='L')
legend("topright",
       legend = sort(top_crimes$Var1), 
       fill = rainbow(nrow(wkday_result)), cex=0.4)

It seems that whether a day is a weekday or a weekend doesn’t affect both the category and the quantity of crimes…So criminals doesn’t have day-offs! SAD! Umm common sense tells me that more crimes take place at night than during the day. Let’s divide the time into day and night!

library(chron)
train$Time <- times(substring(train$Dates,12))
dayNight <- data.frame(Times = times(substring(train$Dates,12)), Cat = train$Category)
breaks <- c(0,6,10,14,18,24)/24
labels <- c("EarlyMorning","Morning","Noon","Afternoon","Evening")
dayNight$ind <- cut(dayNight$Times, breaks, labels, include.lowest = TRUE)
train$TimeInDay <- cut(train$Time, breaks, labels, include.lowest = T)
dayNight
g <- ggplot(dayNight, aes(ind))
g + geom_bar() + geom_bar(aes(fill=Cat)) + ggtitle("Crime in a day") + theme(axis.text.x = element_text(angle=90,hjust=1))

dayNight <- data.frame(Times = times(substring(train$Dates,12)), Cat = train$Category)
breaks <- c(0,5, 20, 24)/24
labels <- c("Night","Day","Night2")
dayNight$ind <- cut(dayNight$Times, breaks, labels, include.lowest = TRUE)
train$DayNight <- cut(train$Time, breaks, labels, include.lowest = T)
dayNight$ind <- gsub("Night2", "Night", dayNight$ind)
train$DayNight <- gsub("Night2", "Night", train$DayNight)
g <- ggplot(dayNight, aes(ind))
g + geom_bar() + geom_bar(aes(fill=Cat)) + ggtitle("Crime in a day") + theme(axis.text.x = element_text(angle=90,hjust=1))

Also, maybe crimes are correlated with seasons? Let’s check it out! But again, the incompleteness of the data causes us a lot of trouble and might lead to inaccuracies, so some sort of averaging is needed.

seasons <- train
# March, April, May <=> Spring
seasons$Season <- "Spring"
train$Season <- "Spring"
# June, July, August <=> Summer
seasons[seasons$Month == "06" | seasons$Month == "07" | seasons$Month == "08",]$Season <- "Summer"
train[train$Month == "06" | train$Month == "07" | train$Month == "08",]$Season <- "Summer"
# September, October, November <=> Fall
seasons[seasons$Month == "09" | seasons$Month == "10" | seasons$Month == "11",]$Season <- "Fall"
train[train$Month == "09" | train$Month == "10" | train$Month == "11",]$Season <- "Fall"
# December, January, February <=> Winter
seasons[seasons$Month == "12" | seasons$Month == "01" | seasons$Month == "02",]$Season <- "Winter"
train[train$Month == "12" | train$Month == "01" | train$Month == "02",]$Season <- "Winter"
season_df <- (data.frame(Season=seasons$Season, Category=seasons$Category))
g <- ggplot(season_df, aes(Season))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Crime by Season") + theme(axis.text.x = element_text(angle=90,hjust=1))

PdDistrict is still unchecked.

area_df <- (data.frame(District=train$PdDistrict, Category=train$Category))
area_df
g <- ggplot(area_df, aes(District))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Crime by District") + theme(axis.text.x = element_text(angle=90,hjust=1))

Let’s do some text mining as this is by far the most useful information! First, deal with synonyms of the cats

train$Keyword <- NA
library("xlsx")
library("wordnet")
#setDict("/usr/local/Cellar/wordnet/3.1")
#initDict()
old_cats <- tolower(names(sort(table(train$Category), decreasing=F)))
for (cat in old_cats) {
  origin_cat <- cat
  if (grepl("/", cat)) {
    cat <- strsplit(cat, "/")
    for (word in cat[[1]]) {
      syn_list <- synonyms(word, "NOUN")
      pattern <- paste(syn_list, collapse = "|")
      train$Keyword[grepl(pattern, train$Descript)] <- origin_cat
    }
  } else {
    cat <- removeWords(cat, stopwords("en"))
    cat <- trimws(gsub(" +", " ", cat)) 
    cat <- strsplit(cat, " ")
    for (word in cat[[1]]) {
      patter <- paste(synonyms(word, "NOUN"), collapse = "|")
      train$Keyword[grepl(pattern, train$Descript)] <- origin_cat
    }
  }
}

Words with top frequency.

# Words in Descript with top frequency
freq_words <- (tolower(freq_words))
remove <- c("FROM", "WITH")
freq_words <- freq_words[!freq_words %in% remove]
for (word in freq_words) {
  train$Keyword[grepl(word, train$Descript)] <- word
}
#freq_words
#freq_words_str <- paste(freq_words, collapse = "|")
#freq_words_str

Lastly, perfect matches.

library(tm)
library(stringr)
# Preprocess the categories 
train$Descript <- tolower(train$Descript)
old_cats <- tolower(names(sort(table(train$Category), decreasing=F)))
for (cat in old_cats) {
  if (grepl("/", cat)) {
    pattern <- gsub("/", "|", cat)
    #print(cat)
  } else {
    pattern <- removeWords(cat, stopwords("en"))
    pattern <- trimws(gsub(" +", " ", pattern)) 
  }
  train$Keyword[grepl(pattern, train$Descript)] <- cat
}

Finally we need to take a look at the resolution…

res_df <- data.frame(Resolution = train$Resolution, Category = train$Category)
g <- ggplot(res_df, aes(Resolution))
g + geom_bar() + geom_bar(aes(fill=Category)) + ggtitle("Crime Resolutions") + theme(axis.text.x = element_text(angle=90,hjust=1)) +
  theme(legend.position="right") + theme(legend.text = element_text(size=5))

colnames(train)[which(names(train) == "Keyword")] <- "Keyword"
prop.table(table(is.na(train$Keyword)))

FALSE 
    1 
table(train$Keyword)

                  aided                  arrest                   arson                 assault 
                  30318                    9011                    1483                   17633 
                   auto              automobile                 battery                 bribery 
                     82                   26897                   33791                     148 
               burglary                    case           drug/narcotic            embezzlement 
                  38956                    2259                   11335                     197 
                  entry               extortion  forgery/counterfeiting                   fraud 
                      1                     256                    7907                    4295 
               gambling              kidnapping           larceny/theft                 license 
                    144                     613                  187437                     885 
              loitering                    lost                mischief          other offenses 
                   1383                   38153                   10482                      42 
pornography/obscene mat              possession                property            prostitution 
                    144                   34417                   16501                    7227 
      recovered vehicle                 robbery                 runaway                  stolen 
                   6796                   22507                    1946                   11226 
        stolen property                 suicide               suspended              suspicious 
                   4292                     508                   26839                    3164 
         suspicious occ                 traffic                trespass               vandalism 
                  22280                   22303                    6766                   34070 
                vehicle           vehicle theft               violation                 warrant 
                  15558                  167594                   25908                   24295 
unique(train$Keyword)
 [1] "warrant"                 "traffic"                 "larceny/theft"           "automobile"             
 [5] "vehicle theft"           "vandalism"               "property"                "robbery"                
 [9] "assault"                 "lost"                    "suspicious"              "aided"                  
[13] "violation"               "suspended"               "stolen"                  "burglary"               
[17] "recovered vehicle"       "forgery/counterfeiting"  "possession"              "drug/narcotic"          
[21] "arrest"                  "stolen property"         "trespass"                "fraud"                  
[25] "battery"                 "vehicle"                 "suspicious occ"          "runaway"                
[29] "prostitution"            "mischief"                "arson"                   "pornography/obscene mat"
[33] "case"                    "license"                 "kidnapping"              "suicide"                
[37] "bribery"                 "loitering"               "embezzlement"            "extortion"              
[41] "gambling"                "auto"                    "other offenses"          "entry"                  

Need to improve…Reduce TRUE values…

table(train$Address)

               0 Block of  HARRISON ST                     0 Block of 10TH AV 
                                     1                                      5 
                    0 Block of 10TH ST                     0 Block of 11TH ST 
                                    49                                     48 
                    0 Block of 12TH AV                     0 Block of 12TH ST 
                                     7                                    436 
                    0 Block of 13TH ST                     0 Block of 14TH AV 
                                    46                                      6 
                    0 Block of 14TH ST                     0 Block of 15TH AV 
                                    59                                      6 
                    0 Block of 15TH ST                     0 Block of 16TH AV 
                                     7                                      5 
                    0 Block of 17TH AV                     0 Block of 18TH AV 
                                     6                                     17 
                    0 Block of 19TH AV                      0 Block of 1ST ST 
                                     7                                    153 
                    0 Block of 20TH AV                     0 Block of 21ST AV 
                                     7                                     20 
                    0 Block of 22ND AV                     0 Block of 25TH AV 
                                     9                                     18 
                    0 Block of 26TH AV                     0 Block of 27TH AV 
                                     7                                      3 
                    0 Block of 27TH ST                     0 Block of 28TH ST 
                                     8                                     48 
                    0 Block of 29TH ST                      0 Block of 2ND AV 
                                    55                                      2 
                     0 Block of 2ND ST                     0 Block of 30TH ST 
                                   147                                     65 
                    0 Block of 36TH AV                      0 Block of 3RD AV 
                                     4                                      4 
                     0 Block of 3RD ST                      0 Block of 4TH ST 
                                   409                                    696 
                     0 Block of 5TH AV                      0 Block of 5TH ST 
                                    23                                    511 
              0 Block of 5THSTNORTH ST                      0 Block of 6TH AV 
                                   332                                     32 
                     0 Block of 6TH ST                      0 Block of 7TH AV 
                                  2884                                     26 
                     0 Block of 7TH ST               0 Block of 7THSTNORTH ST 
                                   394                                      3 
                     0 Block of 8TH AV                      0 Block of 8TH ST 
                                     3                                    253 
                     0 Block of 9TH AV                      0 Block of 9TH ST 
                                     6                                    352 
                   0 Block of ABBEY ST                  0 Block of ACEVEDO AV 
                                    18                                     23 
                   0 Block of ACTON ST                      0 Block of ADA CT 
                                     4                                     12 
                   0 Block of ADAIR ST                  0 Block of ADDISON ST 
                                    36                                     71 
                   0 Block of ADLER ST                  0 Block of ADMIRAL AV 
                                     9                                     35 
                  0 Block of AERIAL WY                    0 Block of AGNON AV 
                                     5                                     14 
                    0 Block of AGUA WY                    0 Block of AHERN WY 
                                    31                                      3 
                 0 Block of ALADDIN TR                    0 Block of ALANA WY 
                                     4                                      1 
                 0 Block of ALBERTA ST                   0 Block of ALBION ST 
                                     4                                     99 
                   0 Block of ALDER ST                  0 Block of ALEMANY BL 
                                    12                                      4 
                0 Block of ALHAMBRA ST                    0 Block of ALLEN ST 
                                    16                                      1 
                 0 Block of ALLISON ST                  0 Block of ALLSTON WY 
                                    24                                     13 
                    0 Block of ALMA ST                  0 Block of ALMADEN CT 
                                    15                                     19 
                   0 Block of ALOHA AV                    0 Block of ALPHA ST 
                                    10                                     37 
                  0 Block of ALPINE TR                 0 Block of ALTA MAR WY 
                                    16                                      1 
                    0 Block of ALTA ST                  0 Block of ALTAMAR WY 
                                    31                                      3 
                   0 Block of ALTON AV                 0 Block of ALVARADO ST 
                                     4                                     30 
                  0 Block of ALVISO ST                   0 Block of AMAZON AV 
                                    28                                      8 
                   0 Block of AMBER DR                     0 Block of AMES ST 
                                    10                                      2 
                0 Block of AMETHYST WY                  0 Block of AMHERST ST 
                                    15                                      2 
                0 Block of ANDERSON ST                  0 Block of ANDOVER ST 
                                    49                                      7 
                  0 Block of ANKENY ST                0 Block of ANNAPOLIS TR 
                                    13                                     14 
                   0 Block of ANNIE ST                  0 Block of ANTHONY ST 
                                    11                                      1 
                 0 Block of ANTONIO ST               0 Block of ANZA VISTA AV 
                                    85                                      1 
               0 Block of ANZAVISTA AV                   0 Block of APOLLO ST 
                                    21                                     42 
                 0 Block of APPAREL WY                 0 Block of APPLETON AV 
                                    25                                     22 
                   0 Block of APTOS AV                0 Block of AQUAVISTA WY 
                                     9                                      5 
                   0 Block of ARAGO ST                    0 Block of ARBOR ST 
                                    20                                     15 
                    0 Block of ARCH ST                     0 Block of ARCO WY 
                                     2                                      1 
                  0 Block of ARDATH CT                0 Block of ARDENWOOD WY 
                                    83                                      2 
         0 Block of ARELIOUS WALKER DR                 0 Block of ARELLANO AV 
                                     4                                      4 
                  0 Block of ARGENT AL                 0 Block of ARGONAUT AV 
                                    15                                     26 
                0 Block of ARGUELLO BL                 0 Block of ARKANSAS ST 
                                    10                                     26 
                  0 Block of ARLETA AV                0 Block of ARLINGTON ST 
                                    57                                     25 
                  0 Block of ARMORY DR                   0 Block of ARNOLD AV 
                                     2                                     20 
                  0 Block of ARROYO WY                  0 Block of ASHBURY ST 
                                    10                                     34 
                 0 Block of ASHBURY TR                   0 Block of ASHTON AV 
                                    18                                     15 
                 0 Block of ATALAYA TR                   0 Block of ATHENS ST 
                                     8                                     46 
                  0 Block of AUBURN ST                   0 Block of AUGUST AL 
                                     4                                      8 
                 0 Block of AUGUSTA ST                   0 Block of AUSTIN ST 
                                     9                                      8 
                  0 Block of AVALON AV         0 Block of AVENUE OF THE PALMS 
                                    22                                     25 
                   0 Block of AVERY ST                    0 Block of AVILA ST 
                                    16                                     19 
                   0 Block of AZTEC ST                    0 Block of BACHE ST 
                                    14                                     14 
                   0 Block of BACON ST                    0 Block of BADEN ST 
                                     4                                     11 
                  0 Block of BADGER ST                    0 Block of BAKER ST 
                                    13                                     29 
                  0 Block of BALBOA ST                  0 Block of BALCETA AV 
                                    14                                      9 
                 0 Block of BALDWIN CT                    0 Block of BALHI CT 
                                    67                                     12 
                   0 Block of BALMY ST                0 Block of BALTIMORE WY 
                                    14                                     14 
                 0 Block of BANBURY DR                    0 Block of BANKS ST 
                                     6                                      3 
                  0 Block of BANNAM PL                0 Block of BANNECKER WY 
                                     8                                     48 
                 0 Block of BANNOCK ST                0 Block of BARCELONA AV 
                                    15                                     18 
               0 Block of BARNEVELD AV                 0 Block of BARTLETT ST 
                                     2                                    122 
                    0 Block of BASS CR                  0 Block of BATTERY ST 
                                     7                                     61 
               0 Block of BAY SHORE BL                      0 Block of BAY ST 
                                     5                                     60 
         0 Block of BAYSIDE VILLAGE PL           0 Block of BAYSIDEVILLAGE PL 
                                     7                                     35 
                 0 Block of BAYVIEW ST                  0 Block of BAYWOOD CT 
                                    77                                      8 
                   0 Block of BEACH ST                0 Block of BEACHMONT DR 
                                    75                                     10 
                   0 Block of BEALE ST                 0 Block of BEATRICE LN 
                                    75                                    106 
                0 Block of BEAUMONT AV                   0 Block of BEAVER ST 
                                    23                                     35 
                 0 Block of BECKETT ST                     0 Block of BEHR AV 
                                     9                                     11 
                0 Block of BEIDEMAN ST                  0 Block of BELCHER ST 
                                    16                                     72 
                  0 Block of BELDEN ST                 0 Block of BELGRAVE AV 
                                    60                                     10 
                    0 Block of BELL CT                  0 Block of BELLAIR PL 
                                    31                                      7 
              0 Block of BELLAVISTA WY                    0 Block of BELLE AV 
                                     2                                     15 
                0 Block of BELLEVUE AV                  0 Block of BELMONT AV 
                                     1                                      5 
               0 Block of BELVEDERE ST                    0 Block of BEMIS ST 
                                    40                                     21 
              0 Block of BENNINGTON ST                   0 Block of BENTON AV 
                                    16                                     39 
                  0 Block of BERGEN PL                 0 Block of BERKELEY WY 
                                     2                                     23 
               0 Block of BERKSHIRE WY           0 Block of BERNAL HEIGHTS BL 
                                     6                                      1 
                 0 Block of BERNARD ST                  0 Block of BERNICE ST 
                                    18                                     37 
                   0 Block of BERRY ST                   0 Block of BERTHA LN 
                                     6                                    204 
             0 Block of BERTIEMINOR LN                  0 Block of BERWICK PL 
                                     8                                      3 
                  0 Block of BESSIE ST                   0 Block of BEULAH ST 
                                    23                                     85 
                 0 Block of BEVERLY ST                     0 Block of BIRD ST 
                                    50                                      7 
                  0 Block of BISHOP ST               0 Block of BLACKSTONE CT 
                                    13                                      3 
                   0 Block of BLAIR TR                    0 Block of BLAKE ST 
                                    15                                     30 
                 0 Block of BLANKEN AV                  0 Block of BLUXOME ST 
                                    20                                    109 
               0 Block of BLYTHDALE AV                 0 Block of BOARDMAN PL 
                                   489                                     57 
             0 Block of BOB KAUFMAN AL                0 Block of BONIFACIO ST 
                                     8                                     16 
                  0 Block of BONITA ST                  0 Block of BONVIEW ST 
                                     8                                     18 
                  0 Block of BORICA ST                 0 Block of BOSWORTH ST 
                                    20                                     24 
                0 Block of BOUTWELL ST                   0 Block of BOWMAN CT 
                                    22                                     38 
                0 Block of BOYLSTON ST                 0 Block of BRADFORD ST 
                                     1                                     42 
                   0 Block of BRADY ST                  0 Block of BRANNAN ST 
                                    56                                      6 
                   0 Block of BRANT AL                   0 Block of BRAZIL AV 
                                     1                                     18 
                   0 Block of BREEN PL                0 Block of BRENTWOOD AV 
                                     4                                     27 
               0 Block of BRETHARTE TR                 0 Block of BREWSTER ST 
                                     8                                     15 
              0 Block of BRIDGEVIEW DR                   0 Block of BRIGHT ST 
                                    77                                      4 
                0 Block of BRIGHTON AV                  0 Block of BRITTON ST 
                                    40                                     17 
                   0 Block of BROAD ST                0 Block of BROADMOOR DR 
                                    78                                     15 
                0 Block of BROADWAY ST                0 Block of BRODERICK ST 
                                    77                                     36 
                0 Block of BROMPTON AV                   0 Block of BRONTE ST 
                                     9                                     58 
                   0 Block of BROOK ST                0 Block of BROOKDALE AV 
                                    17                                    461 
                0 Block of BROOKLYN PL                  0 Block of BROSNAN ST 
                                     6                                     47 
            0 Block of BROTHERHOOD WAY                    0 Block of BRUCE AV 
                                     2                                     53 
                 0 Block of BRUMISS TR                0 Block of BRUNSWICK ST 
                                    12                                     12 
                   0 Block of BRUSH PL                 0 Block of BRUSSELS ST 
                                    11                                     11 
                  0 Block of BRYANT ST                 0 Block of BUCARELI DR 
                                    79                                     45 
                0 Block of BUCHANAN ST               0 Block of BUCKINGHAM WY 
                                    27                                     30 
        0 Block of BUENA VISTA EAST AV             0 Block of BUENA VISTA TER 
                                     7                                     48 
          0 Block of BUENAVISTAEAST AV                 0 Block of BURLWOOD DR 
                                    33                                     37 
                 0 Block of BURNETT AV                    0 Block of BURNS PL 
                                    13                                      2 
                0 Block of BURNSIDE AV                     0 Block of BURR AV 
                                     8                                     27 
                 0 Block of BURRITT ST                  0 Block of BURROWS ST 
                                     4                                      4 
                    0 Block of BUSH ST                    0 Block of BUTTE PL 
                                    33                                      2 
                   0 Block of BYRON CT                   0 Block of BYXBEE ST 
                                    37                                     24 
                0 Block of CABRILLO ST                   0 Block of CADELL PL 
                                    22                                      6 
                   0 Block of CAINE AV                    0 Block of CAIRE TR 
                                    69                                     20 
               0 Block of CALEDONIA ST                  0 Block of CALGARY ST 
                                     7                                     17 
                 0 Block of CALHOUN TR               0 Block of CALIFORNIA ST 
                                     6                                    183 
                  0 Block of CAMBON DR                0 Block of CAMBRIDGE ST 
                                   102                                     20 
                0 Block of CAMELLIA AV                    0 Block of CAMEO WY 
                                    24                                      8 
                 0 Block of CAMERON WY                     0 Block of CAMP ST 
                                   458                                     45 
                0 Block of CAMPBELL AV                  0 Block of CAMPTON PL 
                                    11                                     86 
                  0 Block of CANYON DR               0 Block of CAPISTRANO AV 
                                    22                                      9 
                 0 Block of CAPITOL AV                     0 Block of CAPP ST 
                                     5                                     97 
                   0 Block of CAPRA WY                     0 Block of CARD AL 
                                    20                                     12 
                0 Block of CARDENAS AV                    0 Block of CARGO WY 
                                     5                                     25 
                    0 Block of CARL ST                   0 Block of CARMEL ST 
                                    56                                     22 
               0 Block of CARMELITA ST                0 Block of CARNELIAN WY 
                                    22                                      8 
                0 Block of CAROLINA ST                0 Block of CARPENTER CT 
                                    16                                      7 
                    0 Block of CARR ST                   0 Block of CARRIE ST 
                                   104                                      1 
                0 Block of CARRIZAL ST                   0 Block of CARSON ST 
                                    40                                     11 
                  0 Block of CARVER ST                     0 Block of CASA WY 
                                    16                                     33 
                 0 Block of CASCADE WK                  0 Block of CASELLI AV 
                                     1                                     38 
                0 Block of CASHMERE ST                0 Block of CASSANDRA CT 
                                   286                                     22 
                 0 Block of CASTELO AV                0 Block of CASTENADA AV 
                                    10                                      8 
                0 Block of CASTILLO ST             0 Block of CASTLE MANOR AV 
                                    42                                      4 
                  0 Block of CASTLE ST              0 Block of CASTLEMANOR AV 
                                     8                                     32 
                  0 Block of CASTRO ST                   0 Block of CAYUGA AV 
                                   299                                     32 
                   0 Block of CEDAR ST                    0 Block of CEDRO AV 
                                    73                                     15 
                 0 Block of CENTRAL AV                    0 Block of CERES ST 
                                    30                                     54 
                0 Block of CERRITOS AV                0 Block of CERVANTES BL 
                                    19                                     63 
                  0 Block of CHABOT TR                 0 Block of CHANCERY LN 
                                     6                                      9 
0 Block of CHARLES J BRENHAM PLORTH ST                 0 Block of CHARLTON CT 
                                     2                                      4 
             0 Block of CHARTER OAK AV               0 Block of CHARTEROAK AV 
                                    11                                     25 
                 0 Block of CHATHAM PL              0 Block of CHATTANOOGA ST 
                                     1                                     21 
                  0 Block of CHAVES AV                  0 Block of CHENERY ST 
                                    10                                     90 
                  0 Block of CHERRY ST                  0 Block of CHESLEY ST 
                                     4                                      2 
                 0 Block of CHESTER AV                 0 Block of CHESTNUT ST 
                                     5                                     19 
                 0 Block of CHICAGO WY                    0 Block of CHILD ST 
                                    23                                      4 
                 0 Block of CHILTON AV              0 Block of CHRISTOPHER DR 
                                     2                                      7 
                   0 Block of CHULA LN                0 Block of CHUMASERO DR 
                                     9                                    216 
                  0 Block of CHURCH ST                  0 Block of CIELITO DR 
                                   117                                     54 
                0 Block of CIRCULAR AV                 0 Block of CITYVIEW WY 
                                     8                                     13 
               0 Block of CLAIRVIEW CT                0 Block of CLAREMONT BL 
                                     4                                      5 
                0 Block of CLARENCE PL                0 Block of CLARENDON AV 
                                    19                                     26 
                 0 Block of CLARION AL                   0 Block of CLAUDE LN 
                                    49                                     35 
                    0 Block of CLAY ST                  0 Block of CLAYTON ST 
                                   104                                     20 
              0 Block of CLEARFIELD DR                0 Block of CLEARVIEW CT 
                                    17                                      9 
                  0 Block of CLEARY CT                  0 Block of CLEMENT ST 
                                    76                                     35 
              0 Block of CLEMENTINA ST                0 Block of CLEVELAND ST 
                                    98                                      8 
                0 Block of CLIFFORD TR             0 Block of CLINTON PARK ST 
                                    25                                      1 
             0 Block of CLINTONPARK ST                  0 Block of CLIPPER ST 
                                     5                                     11 
                  0 Block of CLOVER ST                    0 Block of CLYDE ST 
                                     7                                      5 
                  0 Block of CODMAN PL                    0 Block of COLBY ST 
                                     1                                     16 
                    0 Block of COLE ST                0 Block of COLERIDGE ST 
                                    17                                     55 
        0 Block of COLIN P KELLY JR ST                    0 Block of COLIN PL 
                                     8                                      1 
           0 Block of COLINPKELLYJR ST                  0 Block of COLLEGE AV 
                                     8                                     19 
                 0 Block of COLLEGE TR              0 Block of COLLINGWOOD ST 
                                    17                                     66 
                 0 Block of COLLINS ST                 0 Block of COLONIAL WY 
                                    25                                      6 
                  0 Block of COLTON ST          0 Block of COLUMBIA SQUARE ST 
                                    11                                      6 
          0 Block of COLUMBIASQUARE ST                 0 Block of COLUMBUS AV 
                                    71                                     27 
                  0 Block of COLUSA PL                   0 Block of COMMER CT 
                                     1                                    126 
              0 Block of COMMERCIAL ST             0 Block of COMMONWEALTH AV 
                                     2                                     20 
                 0 Block of CONCORD ST                    0 Block of CONGO ST 
                                    39                                      3 
                0 Block of CONKLING ST              0 Block of CONNECTICUT ST 
                                   213                                     27 
                  0 Block of CONRAD ST             0 Block of CONSERVATORY DR 
                                    16                                      5 
               0 Block of CONSTANSO WY                 0 Block of CONVERSE ST 
                                     3                                      2 
                    0 Block of COOK ST                   0 Block of COOPER AL 
                                    33                                      3 
                    0 Block of CORA ST                    0 Block of CORAL RD 
                                    15                                      5 
                 0 Block of CORBETT AV                  0 Block of CORDOVA ST 
                                     3                                     59 
                0 Block of CORNWALL ST                   0 Block of CORONA ST 
                                    15                                     24 
                0 Block of CORTLAND AV                   0 Block of CORWIN ST 
                                   198                                     19 
                   0 Block of COSMO PL                     0 Block of COSO AV 
                                    37                                     49 
                   0 Block of COSTA ST                  0 Block of COTTAGE RW 
                                    10                                      1 
                  0 Block of COTTER ST              0 Block of COUNTRYCLUB DR 
                                    48                                      9 
                0 Block of COVENTRY CT                 0 Block of COVENTRY LN 
                                    10                                      3 
                0 Block of CRAGMONT AV                    0 Block of CRAGS CT 
                                    32                                     13 
                   0 Block of CRANE ST                0 Block of CRANLEIGH DR 
                                    64                                      7 
                0 Block of CRESCENT AV                  0 Block of CRESCIO CT 
                                    53                                     10 
                  0 Block of CRESPI DR              0 Block of CRESTAVISTA DR 
                                    21                                      2 
               0 Block of CRESTLAKE DR                0 Block of CRESTLINE DR 
                                    24                                    147 
               0 Block of CRESTMONT DR                    0 Block of CROSS ST 
                                     3                                      6 
                   0 Block of CROWN TR                  0 Block of CRYSTAL ST 
                                     4                                     60 
                  0 Block of CUESTA CT                  0 Block of CULEBRA TR 
                                     2                                      5 
              0 Block of CUMBERLAND ST               0 Block of CUNNINGHAM PL 
                                    56                                     18 
                  0 Block of CURTIS ST                  0 Block of CUSHMAN ST 
                                    63                                      8 
                  0 Block of CUTLER AV                   0 Block of CUVIER ST 
                                    14                                     16 
                 0 Block of CYPRESS ST      0 Block of CYRIL MAGNIN STORTH ST 
                                    14                                     52 
                   0 Block of CYRUS PL                   0 Block of DAKOTA ST 
                                     3                                    558 
                0 Block of DALEWOOD WY           0 Block of DANIEL BURNHAM CT 
                                     8                                      9 
           0 Block of DANIELBURNHAM CT                   0 Block of DANTON ST 
                                    84                                     21 
                 0 Block of DANVERS ST                   0 Block of DARIEN WY 
                                     7                                     24 
                 0 Block of DARRELL PL                0 Block of DARTMOUTH ST 
                                     9                                     18 
        0 Block of DASHIELL HAMMETT ST                    0 Block of DAVIS ST 
                                    95                                      4 
                0 Block of DAWNVIEW WY                   0 Block of DAWSON PL 
                                    12                                      3 
                     0 Block of DAY ST                  0 Block of DE LONG ST 
                                    26                                     14 
             0 Block of DE MONTFORT AV                  0 Block of DE SOTO ST 
                                     2                                      1 
                 0 Block of DE WOLF ST                 0 Block of DEARBORN ST 
                                     2                                     43 
                  0 Block of DEBOOM ST                  0 Block of DECATUR ST 
                                     2                                     18 
                  0 Block of DECKER AL                   0 Block of DEDMAN CT 
                                     1                                    167 
                  0 Block of DEHARO ST                    0 Block of DEHON ST 
                                     9                                      3 
               0 Block of DEL MONTE ST                 0 Block of DEL VALE AV 
                                     2                                      1 
                  0 Block of DELANO AV                  0 Block of DELGADO PL 
                                    26                                      2 
               0 Block of DELLBROOK AV                   0 Block of DELMAR ST 
                                    17                                     41 
                0 Block of DELMONTE ST                   0 Block of DELONG ST 
                                    15                                     52 
                   0 Block of DELTA ST                  0 Block of DELVALE AV 
                                    65                                      1 
                  0 Block of DEMING ST               0 Block of DEMONTFORT AV 
                                     6                                     33 
                0 Block of DENSLOWE DR                    0 Block of DERBY ST 
                                    22                                     27 
                 0 Block of DESMOND ST                   0 Block of DESOTO ST 
                                    27                                     16 
              0 Block of DEVONSHIRE WY                   0 Block of DEWOLF ST 
                                    13                                      1 
                 0 Block of DIAMOND ST                    0 Block of DIANA ST 
                                    56                                     10 
                    0 Block of DIAZ AV                 0 Block of DICHIERA CT 
                                    44                                     10 
                   0 Block of DIGBY ST               0 Block of DIVISADERO ST 
                                    18                                     49 
                0 Block of DIVISION ST                    0 Block of DODGE PL 
                                    31                                     26 
                 0 Block of DOLORES ST                  0 Block of DOLORES TR 
                                    67                                      9 
                  0 Block of DORADO TR                 0 Block of DORANTES AV 
                                    30                                      2 
              0 Block of DORCHESTER WY                     0 Block of DORE ST 
                                     2                                    763 
                   0 Block of DORIC AL                  0 Block of DORLAND ST 
                                     5                                     60 
                  0 Block of DORMAN AV                0 Block of DORMITORY RD 
                                    38                                      3 
              0 Block of DOUBLEROCK ST                 0 Block of DOUGLASS ST 
                                   150                                     30 
                     0 Block of DOW PL                   0 Block of DOWNEY ST 
                                    16                                     36 
                   0 Block of DRAKE ST                    0 Block of DRUMM ST 
                                     2                                    654 
                  0 Block of DUBLIN ST                   0 Block of DUBOCE AV 
                                    40                                    106 
                   0 Block of DUKES CT                   0 Block of DUNCAN ST 
                                    58                                     19 
                0 Block of DUNCOMBE AL                   0 Block of DUNNES AL 
                                     2                                      2 
                 0 Block of DUNSHEE ST                 0 Block of DUNSMUIR ST 
                                     1                                     22 
                  0 Block of DWIGHT ST                    0 Block of EAGLE ST 
                                    17                                     17 
                 0 Block of EASTMAN ST                 0 Block of EASTWOOD DR 
                                     2                                     20 
                   0 Block of EATON PL                    0 Block of ECKER ST 
                                     3                                      4 
                    0 Block of EDDY ST                    0 Block of EDGAR PL 
                                    71                                     55 
                0 Block of EDGEHILL WY                0 Block of EDINBURGH ST 
                                     5                                     35 
                   0 Block of EDITH ST                     0 Block of EDNA ST 
                                     6                                     22 
                  0 Block of EDWARD ST           0 Block of EL CAMINO DEL MAR 
                                    15                                      1 
               0 Block of EL SERENO CT                  0 Block of ELGIN PARK 
                                     3                                      5 
               0 Block of ELGINPARK ST                0 Block of ELIZABETH ST 
                                    52                                     14 
                     0 Block of ELK ST                   0 Block of ELLERT ST 
                                    71                                      7 
               0 Block of ELLINGTON AV                    0 Block of ELLIS ST 
                                    17                                    172 
               0 Block of ELLSWORTH ST                      0 Block of ELM ST 
                                    16                                      7 
                0 Block of ELMHURST DR                   0 Block of ELMIRA ST 
                                     3                                     18 
               0 Block of ELMIRASOL PL               0 Block of ELPLAZUELA WY 
                                     2                                      3 
                0 Block of ELSERENO CT                    0 Block of ELSIE ST 
                                     7                                     43 
                0 Block of ELVERANO WY                   0 Block of ELWOOD ST 
                                     7                                      3 
                 0 Block of EMERSON ST                    0 Block of EMERY LN 
                                     6                                     12 
                 0 Block of ENCANTO AV                  0 Block of ENCLINE CT 
                                    18                                     10 
              0 Block of ENTERPRISE ST                  0 Block of ENTRADA CT 
                                     4                                     24 
                    0 Block of ERIE ST                   0 Block of ERVINE ST 
                                    56                                     34 
                 0 Block of ESCOLTA WY                0 Block of ESCONDIDO AV 
                                     9                                     19 
               0 Block of ESMERALDA AV                 0 Block of ESPANOLA ST 
                                     1                                     76 
                 0 Block of ESQUINA DR                    0 Block of ESSEX ST 
                                    29                                     53 
                  0 Block of ESTERO AV                   0 Block of EUCLID AV 
                                    13                                      3 
                 0 Block of EUGENIA AV                   0 Block of EUREKA ST 
                                    26                                     29 
                  0 Block of EVELYN WY                0 Block of EVERGLADE DR 
                                     2                                     11 
                 0 Block of EVERSON ST                    0 Block of EWING TR 
                                    11                                      1 
               0 Block of EXCELSIOR AV            0 Block of EXECUTIVEPARK BL 
                                    40                                      4 
                  0 Block of EXETER ST                     0 Block of FAIR AV 
                                    60                                     14 
               0 Block of FAIR OAKS ST                0 Block of FAIRFIELD WY 
                                     2                                     12 
               0 Block of FAIRMOUNT ST                 0 Block of FAIROAKS ST 
                                    11                                     35 
                  0 Block of FALLON PL                 0 Block of FALMOUTH ST 
                                    11                                     14 
                 0 Block of FANNING WY               0 Block of FARALLONES ST 
                                     5                                    329 
              0 Block of FARNSWORTH LN                   0 Block of FARNUM ST 
                                     1                                      8 
                0 Block of FARRAGUT AV                  0 Block of FARVIEW CT 
                                    31                                      3 
                   0 Block of FAXON AV                  0 Block of FEDERAL ST 
                                    17                                     55 
                   0 Block of FELIX AV                     0 Block of FELL ST 
                                     3                                    261 
                   0 Block of FELLA PL                   0 Block of FELTON ST 
                                     6                                     32 
                    0 Block of FERN ST                 0 Block of FERNWOOD DR 
                                    48                                     13 
                0 Block of FIELDING ST                 0 Block of FILLMORE ST 
                                     3                                     22 
                   0 Block of FLINT ST                    0 Block of FLOOD AV 
                                     5                                     35 
                   0 Block of FLORA ST                 0 Block of FLORENCE ST 
                                    64                                     11 
              0 Block of FLORENTINE AV                  0 Block of FLORIDA ST 
                                    49                                     13 
                  0 Block of FLOWER ST                 0 Block of FOERSTER ST 
                                     3                                      3 
                  0 Block of FOLSOM ST                     0 Block of FONT BL 
                                    64                                     36 
              0 Block of FONTINELLA TR                    0 Block of FOOTE AV 
                                     3                                      7 
                    0 Block of FORD ST              0 Block of FOREST SIDE AV 
                                    45                                      2 
            0 Block of FORESTKNOLLS DR               0 Block of FORESTSIDE AV 
                                     7                                     21 
              0 Block of FORESTVIEW DR                  0 Block of FORTUNA AV 
                                    12                                     20 
                0 Block of FOUNTAIN ST                   0 Block of FRANCE AV 
                                    16                                      6 
                 0 Block of FRANCIS ST                0 Block of FRANCISCO ST 
                                    63                                     99 
               0 Block of FRANCONIA ST             0 Block of FRANK NORRIS ST 
                                     3                                     13 
                0 Block of FRANKLIN ST                 0 Block of FRATESSA CT 
                                   131                                     17 
               0 Block of FREDERICK ST                  0 Block of FREDSON CT 
                                     8                                     10 
                 0 Block of FREELON ST                  0 Block of FREMONT ST 
                                     9                                    135 
                  0 Block of FRESNO ST               0 Block of FRIENDSHIP LN 
                                    12                                     31 
                   0 Block of FRONT ST                   0 Block of FUENTE AV 
                                    47                                     50 
                 0 Block of FUNSTON AV                  0 Block of GABILAN WY 
                                     6                                      2 
                  0 Block of GAISER CT                  0 Block of GALILEE LN 
                                     3                                     35 
                 0 Block of GALINDO AV                0 Block of GALLAGHER LN 
                                     3                                     14 
                 0 Block of GAMBIER ST                   0 Block of GARCES DR 
                                     8                                     37 
                  0 Block of GARCIA AV                   0 Block of GARDEN ST 
                                     5                                      3 
              0 Block of GARDENSIDE DR                 0 Block of GARFIELD ST 
                                    60                                     17 
              0 Block of GARLINGTON CT                 0 Block of GARRISON AV 
                                   181                                     96 
                   0 Block of GATES ST                 0 Block of GATEVIEW CT 
                                    12                                     16 
                   0 Block of GAVEN ST                  0 Block of GAVIOTA WY 
                                    20                                     11 
                   0 Block of GEARY ST                  0 Block of GELLERT DR 
                                   230                                      8 
                0 Block of GENEBERN WY                   0 Block of GENEVA AV 
                                    12                                     40 
                0 Block of GENNESEE ST                    0 Block of GENOA PL 
                                     6                                      8 
                  0 Block of GEORGE CT                    0 Block of GERKE AL 
                                    91                                      2 
                0 Block of GERMANIA ST                     0 Block of GETZ ST 
                                    22                                      3 
                  0 Block of GIANTS DR                  0 Block of GILBERT ST 
                                    91                                     17 
                0 Block of GILLETTE AV                   0 Block of GILROY ST 
                                     9                                      9 
                  0 Block of GIRARD ST                0 Block of GLADEVIEW WY 
                                    43                                      1 
               0 Block of GLADSTONE DR                   0 Block of GLADYS ST 
                                    71                                     24 
               0 Block of GLENBROOK AV                 0 Block of GLENDALE ST 
                                     1                                     20 
                0 Block of GLENVIEW DR                   0 Block of GLORIA CT 
                                    17                                      8 
                  0 Block of GLOVER ST                   0 Block of GODEUS ST 
                                    14                                     17 
                  0 Block of GOETHE ST               0 Block of GOETTINGEN ST 
                                     2                                     19 
               0 Block of GOLD MINE DR                     0 Block of GOLD ST 
                                     7                                     24 
                  0 Block of GOLDEN CT              0 Block of GOLDEN GATE AV 
                                     5                                    552 
                0 Block of GOLDMINE DR                   0 Block of GOLETA AV 
                                    51                                      7 
                0 Block of GONZALEZ DR                   0 Block of GORDON ST 
                                    34                                     32 
                  0 Block of GORHAM ST                    0 Block of GOUGH ST 
                                    20                                    287 
                   0 Block of GOULD ST                    0 Block of GRACE ST 
                                    24                                     63 
                 0 Block of GRAFTON AV                  0 Block of GRANADA AV 
                                    12                                     27 
              0 Block of GRAND VIEW AV               0 Block of GRAND VIEW TR 
                                     5                                      1 
               0 Block of GRANDVIEW AV                0 Block of GRANDVIEW TR 
                                    25                                     10 
                   0 Block of GRANT AV                0 Block of GRANVILLE WY 
                                   287                                      1 
                 0 Block of GRATTAN ST                0 Block of GRAYSTONE TR 
                                    13                                     11 
                   0 Block of GREAT HY                    0 Block of GREEN ST 
                                     2                                     32 
               0 Block of GREENVIEW CT                0 Block of GREENWOOD AV 
                                     4                                      8 
                0 Block of GRIJALVA DR                    0 Block of GROVE ST 
                                    74                                    984 
                0 Block of GUERRERO ST               0 Block of GUTTENBERG ST 
                                    46                                     17 
                     0 Block of GUY PL                     0 Block of HAHN ST 
                                    26                                     19 
                  0 Block of HAIGHT ST                     0 Block of HALE ST 
                                    70                                     30 
                  0 Block of HALLAM ST                  0 Block of HALLECK ST 
                                    50                                      6 
                0 Block of HAMILTON ST                  0 Block of HANCOCK ST 
                                     8                                     37 
                  0 Block of HANGAH ST                  0 Block of HANOVER ST 
                                     2                                     22 
                  0 Block of HARBOR RD                   0 Block of HARDIE PL 
                                   324                                      1 
                 0 Block of HARDING RD                     0 Block of HARE ST 
                                    91                                     37 
                0 Block of HARKNESS AV                   0 Block of HARLAN PL 
                                     1                                      3 
                  0 Block of HAROLD AV                   0 Block of HARPER ST 
                                   368                                     20 
                 0 Block of HARRIET ST               0 Block of HARRINGTON ST 
                                   120                                     52 
                  0 Block of HARRIS PL                 0 Block of HARRISON ST 
                                     2                                    143 
                   0 Block of HARRY ST                 0 Block of HARTFORD ST 
                                     2                                     45 
                 0 Block of HARVARD ST                 0 Block of HASTINGS TR 
                                     7                                      1 
                  0 Block of HATTIE ST                 0 Block of HAVELOCK ST 
                                    10                                     15 
                  0 Block of HAVENS ST                  0 Block of HAWKINS LN 
                                     1                                     27 
               0 Block of HAWTHORNE ST                    0 Block of HAYES ST 
                                   152                                     15 
               0 Block of HAZELWOOD AV                   0 Block of HEARST AV 
                                    13                                     11 
                 0 Block of HEATHER AV                    0 Block of HELEN ST 
                                    27                                      5 
                 0 Block of HEMLOCK ST                   0 Block of HEMWAY TR 
                                    70                                      6 
             0 Block of HENRY ADAMS ST                    0 Block of HENRY ST 
                                     7                                     62 
              0 Block of HENRYADAMS ST                   0 Block of HERBST RD 
                                    49                                     11 
                 0 Block of HERMANN ST                0 Block of HERNANDEZ AV 
                                    63                                     23 
                   0 Block of HERON ST                   0 Block of HESTER AV 
                                    36                                      2 
                  0 Block of HEYMAN ST                  0 Block of HICKORY ST 
                                    12                                      5 
                 0 Block of HIDALGO TR                     0 Block of HIGH ST 
                                     3                                     16 
                0 Block of HIGHLAND AV                  0 Block of HIGUERA AV 
                                    20                                     69 
               0 Block of HILIRITAS AV                     0 Block of HILL ST 
                                     2                                     46 
               0 Block of HILLCREST CT                0 Block of HILLPOINT AV 
                                     9                                      3 
                0 Block of HILLVIEW CT                  0 Block of HILLWAY AV 
                                    25                                      3 
                  0 Block of HILTON ST               0 Block of HIMMELMANN PL 
                                     6                                      3 
                 0 Block of HINKLEY WK                     0 Block of HOFF ST 
                                     2                                    277 
                 0 Block of HOFFMAN AV                   0 Block of HOLLIS ST 
                                    16                                      5 
                0 Block of HOLLOWAY AV               0 Block of HOLLY PARK CR 
                                    36                                      2 
               0 Block of HOLLYPARK CR                0 Block of HOLLYWOOD CT 
                                     7                                     12 
                 0 Block of HOLYOKE ST                    0 Block of HOMER ST 
                                    13                                      6 
               0 Block of HOMESTEAD ST                 0 Block of HOMEWOOD CT 
                                    16                                      3 
                 0 Block of HOPKINS AV                   0 Block of HORACE ST 
                                     2                                      2 
                0 Block of HOTALING PL                  0 Block of HOUSTON ST 
                                    10                                      8 
                  0 Block of HOWARD ST                    0 Block of HOWTH ST 
                                   151                                     14 
                  0 Block of HUDSON CT                     0 Block of HUGO ST 
                                    77                                      8 
        0 Block of HUNTERS PT EXPWY EX             0 Block of HUNTERSPOINT BL 
                                     3                                      9 
          0 Block of HUNTERSPTEXPWY EX               0 Block of HUNTINGTON DR 
                                     1                                      5 
                    0 Block of HYDE ST                    0 Block of IDORA AV 
                                    45                                     14 
                 0 Block of IGNACIO ST                 0 Block of ILLINOIS ST 
                                    20                                      3 
                0 Block of IMPERIAL AV                      0 Block of INA CT 
                                     1                                     44 
                    0 Block of INCA LN               0 Block of INDUSTRIAL ST 
                                    15                                      7 
               0 Block of INVERNESS DR                     0 Block of IRIS AV 
                                    11                                      9 
                    0 Block of IRON AL                 0 Block of IRONSHIP PZ 
                                     2                                      5 
                  0 Block of IRVING ST           0 Block of ISADORA DUNCAN PL 
                                     9                                      1 
                    0 Block of ISIS ST                    0 Block of ITALY AV 
                                    37                                     17 
                     0 Block of IVY ST              0 Block of JACK LONDON AL 
                                   144                                      7 
                 0 Block of JACKSON ST                     0 Block of JADE PL 
                                    40                                      3 
                   0 Block of JAKEY CT                   0 Block of JANSEN ST 
                                     8                                      9 
                   0 Block of JASON CT                   0 Block of JASPER PL 
                                     3                                      8 
                    0 Block of JAVA ST                0 Block of JEFFERSON ST 
                                     8                                    243 
                0 Block of JENNINGS CT                 0 Block of JENNINGS ST 
                                    39                                     79 
                  0 Block of JERSEY ST                   0 Block of JESSIE ST 
                                    30                                     34 
          0 Block of JOHN F SHELLEY DR               0 Block of JOHN MAHER ST 
                                     2                                      1 
                    0 Block of JOHN ST             0 Block of JOHNFSHELLEY DR 
                                    15                                     10 
               0 Block of JOHNSTONE DR                    0 Block of JOICE ST 
                                     2                                     28 
                   0 Block of JONES ST                    0 Block of JOOST AV 
                                  1185                                     28 
                  0 Block of JORDAN AV                  0 Block of JOSEPHA AV 
                                    17                                     54 
                  0 Block of JOSIAH AV                      0 Block of JOY ST 
                                    23                                     11 
           0 Block of JUAN BAUTISTA CR             0 Block of JUANBAUTISTA CR 
                                     1                                     12 
                 0 Block of JUANITA WY                    0 Block of JUDAH ST 
                                    16                                     12 
                   0 Block of JULES AV                    0 Block of JULIA ST 
                                   480                                      2 
                  0 Block of JULIAN AV                   0 Block of JULIUS ST 
                                   101                                      1 
                  0 Block of JUNIOR TR                  0 Block of JUNIPER ST 
                                    30                                     24 
          0 Block of JUNIPERO SERRA BL                     0 Block of JURI ST 
                                    12                                     18 
                  0 Block of JUSTIN DR                   0 Block of KAPLAN LN 
                                    52                                      2 
                   0 Block of KAREN CT                     0 Block of KATE ST 
                                    49                                      8 
                  0 Block of KEARNY ST                  0 Block of KELLOCH AV 
                                   155                                     37 
                 0 Block of KEMPTON AV          0 Block of KENNETH REXROTH PL 
                                     7                                      2 
                    0 Block of KENT ST                  0 Block of KENWOOD WY 
                                     1                                      1 
                   0 Block of KEYES AL                 0 Block of KEYSTONE WY 
                                     6                                     29 
                   0 Block of KEZAR DR                     0 Block of KING ST 
                                   375                                     57 
                0 Block of KINGSTON ST                  0 Block of KIRKHAM ST 
                                     5                                      1 
                   0 Block of KISKA RD                 0 Block of KISSLING ST 
                                    93                                     32 
               0 Block of KITTREDGE TR                0 Block of KNOLLVIEW WY 
                                    13                                      6 
                   0 Block of KNOTT CT                0 Block of KRONQUIST CT 
                                     9                                      1 
               0 Block of LA GRANDE AV               0 Block of LAAVANZADA ST 
                                     2                                      6 
               0 Block of LAFAYETTE ST                 0 Block of LAGRANDE AV 
                                    77                                     25 
            0 Block of LAGUNA HONDA BL                   0 Block of LAGUNA ST 
                                     1                                    100 
             0 Block of LAGUNAHONDA BL                0 Block of LAGUNITAS DR 
                                     1                                     20 
                 0 Block of LAIDLEY ST              0 Block of LAKE MERCED BL 
                                    42                                      4 
              0 Block of LAKE SHORE DR                     0 Block of LAKE ST 
                                     1                                     51 
              0 Block of LAKEFOREST CT                0 Block of LAKESHORE DR 
                                     2                                      5 
                0 Block of LAKEVIEW AV                 0 Block of LAKEWOOD AV 
                                    12                                     19 
               0 Block of LAMARTINE ST                  0 Block of LANDERS ST 
                                    19                                     75 
                 0 Block of LANGTON ST                  0 Block of LANSING ST 
                                    90                                     62 
                  0 Block of LAPHAM WY                  0 Block of LAPIDGE ST 
                                    30                                     40 
               0 Block of LAPU LAPU ST                0 Block of LAPU-LAPU ST 
                                     3                                     17 
                  0 Block of LARKIN ST               0 Block of LAS VILLAS CT 
                                    62                                      4 
                  0 Block of LASKIE ST                0 Block of LASVILLAS CT 
                                    14                                     30 
                  0 Block of LATONA ST                    0 Block of LAURA ST 
                                   167                                     31 
                  0 Block of LAUREL ST                  0 Block of LAUSSAT ST 
                                     7                                     24 
                0 Block of LAWRENCE AV              0 Block of LEAVENWORTH ST 
                                    28                                    230 
                 0 Block of LEDYARD ST                      0 Block of LEE AV 
                                   631                                     78 
                   0 Block of LEESE ST              0 Block of LEIDESDORFF ST 
                                    36                                     13 
                  0 Block of LELAND AV                    0 Block of LENOX WY 
                                   182                                     28 
                     0 Block of LEO ST                    0 Block of LEONA TR 
                                    33                                      6 
                   0 Block of LEROY PL                  0 Block of LESSING ST 
                                     4                                     11 
                  0 Block of LEVANT ST                0 Block of LEXINGTON ST 
                                    28                                     39 
                 0 Block of LIBERTY ST                   0 Block of LIEBIG ST 
                                    52                                     75 
                   0 Block of LILAC ST                  0 Block of LILLIAN ST 
                                    59                                     31 
                    0 Block of LILY ST                  0 Block of LINARES AV 
                                    32                                      9 
                 0 Block of LINCOLN CT                  0 Block of LINCOLN WY 
                                     2                                     25 
                   0 Block of LINDA ST                  0 Block of LINDSAY CR 
                                    33                                     14 
                 0 Block of LIPPARD AV                   0 Block of LISBON ST 
                                    25                                     58 
             0 Block of LITTLEFIELD TR                    0 Block of LLOYD ST 
                                    16                                     13 
                   0 Block of LOBOS ST                 0 Block of LOCKSLEY AV 
                                   202                                    101 
                  0 Block of LOCUST ST                    0 Block of LOEHR ST 
                                     9                                     15 
               0 Block of LOMAVISTA TR                  0 Block of LOMBARD ST 
                                    11                                     39 
                  0 Block of LOMITA AV                 0 Block of LONGVIEW CT 
                                    17                                     17 
                  0 Block of LOOMIS ST                    0 Block of LOPEZ AV 
                                    18                                     11 
                 0 Block of LORAINE CT               0 Block of LOS PALMOS DR 
                                    14                                      3 
               0 Block of LOSPALMOS DR           0 Block of LOTTIE BENNETT LN 
                                    11                                      2 
           0 Block of LOTTIEBENNETT LN                   0 Block of LOWELL ST 
                                     8                                      4 
                   0 Block of LOWER TR                   0 Block of LOYOLA TR 
                                    13                                     15 
                 0 Block of LUCERNE ST                    0 Block of LUCKY ST 
                                    11                                     30 
                    0 Block of LUCY ST                   0 Block of LUNADO WY 
                                    48                                     15 
                  0 Block of LUNDYS LN                   0 Block of LUPINE AV 
                                    17                                     48 
                 0 Block of LURLINE ST                  0 Block of LURMONT TR 
                                    13                                      5 
                    0 Block of LUSK AL                    0 Block of LYELL ST 
                                     8                                     25 
                   0 Block of LYNCH ST                0 Block of LYNDHURST DR 
                                     5                                      2 
                    0 Block of LYON ST                   0 Block of MABINI ST 
                                    26                                     11 
                  0 Block of MABREY CT                0 Block of MACEDONIA ST 
                                    22                                      5 
               0 Block of MACONDRAY ST                   0 Block of MADDUX AV 
                                     4                                     46 
                  0 Block of MADERA ST                  0 Block of MADISON ST 
                                    14                                     14 
                  0 Block of MADRID ST                  0 Block of MADRONE AV 
                                    11                                     21 
                0 Block of MAGELLAN AV                 0 Block of MAGNOLIA ST 
                                     9                                     14 
                  0 Block of MAIDEN LN                     0 Block of MAIN ST 
                                   115                                     32 
                0 Block of MAJESTIC AV                 0 Block of MALLORCA WY 
                                    38                                     15 
                   0 Block of MALTA DR               0 Block of MANCHESTER ST 
                                    19                                     35 
                 0 Block of MANGELS AV                    0 Block of MANOR DR 
                                     8                                     29 
                 0 Block of MANSELL ST                0 Block of MANSFIELD ST 
                                    15                                      5 
               0 Block of MANZANITA AV                    0 Block of MAPLE ST 
                                    10                                      2 
                 0 Block of MARCELA AV                  0 Block of MARENGO ST 
                                     6                                      1 
                0 Block of MARGARET AV                 0 Block of MARGRAVE PL 
                                    37                                      4 
                0 Block of MARIETTA DR                   0 Block of MARINA BL 
                                    20                                    354 
                  0 Block of MARION PL                   0 Block of MARIST CT 
                                     2                                     29 
                    0 Block of MARK LN                   0 Block of MARKET ST 
                                    19                                    305 
                   0 Block of MARNE AV                     0 Block of MARS ST 
                                     7                                     18 
                 0 Block of MARSILY ST                  0 Block of MARSTON AV 
                                     3                                      7 
                  0 Block of MARTHA AV                   0 Block of MARVEL CT 
                                    10                                      6 
                 0 Block of MARVIEW WY                     0 Block of MARY ST 
                                     1                                      8 
                   0 Block of MASON ST                  0 Block of MASONIC AV 
                                   910                                     93 
               0 Block of MASSOSOIT ST                    0 Block of MATEO ST 
                                    14                                      4 
                 0 Block of MATTHEW CT                  0 Block of MAYFAIR DR 
                                    40                                     12 
                 0 Block of MAYNARD ST                  0 Block of MAYWOOD DR 
                                    60                                      2 
               0 Block of MC CARTHY AV                 0 Block of MC LAREN AV 
                                    10                                      1 
              0 Block of MCALLISTER ST                 0 Block of MCCARTHY AV 
                                   648                                     28 
                0 Block of MCCOPPIN ST                0 Block of MCCORMICK PL 
                                    76                                      8 
                 0 Block of MCLAREN AV                    0 Block of MCLEA CT 
                                     8                                     21 
                 0 Block of MEACHAM PL              0 Block of MEADOWBROOK DR 
                                     5                                     27 
                    0 Block of MEDA AV                    0 Block of MEDAU PL 
                                    19                                      9 
                   0 Block of MELBA AV                    0 Block of MELRA CT 
                                     7                                     21 
 [ reached getOption("max.print") -- omitted 22228 entries ]
LS0tCnRpdGxlOiAiU2FuIEZyYW5jaXNjbyBDcmltZSBDbGFzc2lmaWNhdGlvbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnRyYWluIDwtIHJlYWQuY3N2KGZpbGU9InRyYWluLmNzdiIsIG5hLnN0cmluZ3M9YygiIikpCnRlc3QgPC0gcmVhZC5jc3YoZmlsZT0idGVzdC5jc3YiLCBuYS5zdHJpbmdzPWMoIiIpKQpzdW1tYXJ5KHRyYWluKQpgYGAKYGBge3J9CmxpYnJhcnkoQW1lbGlhKQptaXNzbWFwKHRyYWluLCBtYWluID0gIk1pc3NpbmcgdmFsdWVzIHZzIG9ic2VydmVkIikKYGBgCgpJdCBzZWVtcyB0aGF0IGhlcmUgYXJlICoqbm8gbWlzc2luZyB2YWx1ZXMqKi4gR3JlYXQhCmBgYHtyfQojIE92ZXJhbGwgc3RydWN0dXJlCnN0cih0cmFpbikKYGBgCi0gVGhlcmUgbWlnaHQgYmUgY2VydGFpbiBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSByZXNvbHV0aW9uIGFuZCB0aGUgdHlwZSBvZiBjcmltZT8KLSBNaWdodCBoYXZlIHNvbWV0aGluZyB0byBkbyB3aXRoIHRoZSBkYXkgb2Ygd2Vlaz8KLSBNYXliZSB3ZSBjYW4gcmVncm91cCBjcmltZXMgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgY2F0ZWdvcmllcz8gT3IganVzdCBzZWxlY3QgdGhlIHRvcCBjcmltZXMgYXMgb3VyIGZvY3VzPwpgYGB7cn0KIyBHZXQgdG8ga25vdyBkYXRhIHR5cGVzCnNhcHBseSh0cmFpbiwgY2xhc3MpCmBgYApgYGB7cn0KIyBzdW1tYXJpemUgdGhlIGNsYXNzIGRpc3RyaWJ1dGlvbgpjYXRfcGVyY2VudGFnZSA8LSBwcm9wLnRhYmxlKHRhYmxlKHRyYWluJENhdGVnb3J5KSkgKiAxMDAKY2JpbmQoZnJlcT10YWJsZSh0cmFpbiRDYXRlZ29yeSksIHBlcmNlbnRhZ2U9Y2F0X3BlcmNlbnRhZ2UpCmBgYAoKYGBge3J9CiMgR2V0IHRvcCBjcmltZXMKY3JpbWVfY2F0ZWdvcmllc19kZiA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHRyYWluJENhdGVnb3J5KSkKY3JpbWVfY2F0ZWdvcmllc19kZlt3aXRoKGNyaW1lX2NhdGVnb3JpZXNfZGYsIG9yZGVyKC1GcmVxKSksXQp0b3BfY3JpbWVzIDwtIGhlYWQoY3JpbWVfY2F0ZWdvcmllc19kZlt3aXRoKGNyaW1lX2NhdGVnb3JpZXNfZGYsIG9yZGVyKC1GcmVxKSksXSwgbj0xMCkKYGBgCgpgYGB7cn0KIyBDcmVhdGUgZGF0YSBmb3IgdGhlIGdyYXBoLgp4IDwtIHRvcF9jcmltZXMkRnJlcQpsYWJlbHMgPC0gdG9wX2NyaW1lcyRWYXIxCnBpZXBlcmNlbnQgPC0gcm91bmQoMTAwKngvc3VtKHgpLCAxKQojIFBsb3QgdGhlIGNoYXJ0LgpwaWUoeCwgbGFiZWxzID0gcGllcGVyY2VudCwgbWFpbiA9ICJUb3AgMTAgQ3JpbWVzIixjb2wgPSByYWluYm93KGxlbmd0aCh4KSkpCmxlZ2VuZCgicmlnaHQiLCBhcy5jaGFyYWN0ZXIobGFiZWxzKSwgY2V4ID0gMC44LAogICBmaWxsID0gcmFpbmJvdyhsZW5ndGgoeCkpKQpgYGAKV2UgY2FuIHNlZSB0aGF0ICoqbGFyY2VueS90aGVmdCoqIGFuZCBub24tY3JpbWluYWwgdGFrZXMgdXAgbXVjaCBvZiB0aGUgcGllLCBmb2xsb3dlZCBieSAqKm5vbi1jcmltaW5hbCoqIGFuZCAqKmFzc3VsdCoqLiAnKipPdGhlciBvZmZlbnNlcyoqJyBhbHNvIGFjY291bnRzIGZvciBhIGxhcmdlIHByb3BvcnRpb24sIGJ1dCBpdCBjb250YWlucyBhbWJpZ3VpdGllcyBhbmQgbGFja3MgaW5mb3JtYXRpb24uCgpJcyB0aGVyZSBhIGRheSBvZiB3ZWVrIHRoYXQgaGFzIHNpZ25pZmljYW50bHkgbW9yZSBjcmltZXMgdGhhbiBvdGhlciBkYXlzPwpUaGUgZGlzdHJpYnV0aW9uIGlzIHJhdGhlciBldmVuLiBCdXQgRnJpZGF5IGlzIHN1cmVseSBhIHBlYWsgKG1heWJlIHBlb3BsZSBjb25zdW1lIG1vcmUgYWZ0ZXIgYSB3ZWVrJ3Mgd29yaykgd2hpbGUgU3VuZGF5IGlzIGEgc2x1bXAgKG1vc3QgcGVvcGxlIHN0YXkgYXQgaG9tZSkuCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCnRhYmxlKHRyYWluJENhdGVnb3J5ICx0cmFpbiREYXlPZldlZWspCmcgPC0gZ2dwbG90KHRyYWluLCBhZXMoRGF5T2ZXZWVrKSkKZyArIGdlb21fYmFyKGFlcyhmaWxsID0gQ2F0ZWdvcnkpKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikKYGBgCkhvdyBkb2VzIGNyaW1pbmFsIGFjdGl2aXRpZXMgY2hhbmdlIG92ZXIgdGhlIHllYXJzPyBEb2VzIGl0IGluY3JlYXNlIG9yIGRlY3JlYXNlIG9yIHN0YXkgdGhlIHNhbWU/CgpgYGB7cn0KdHJhaW4kWWVhciA8LSBzdWJzdHJpbmcodHJhaW4kRGF0ZXMsIDEsIDQpCnRyYWluJE1vbnRoIDwtIHN1YnN0cmluZyh0cmFpbiREYXRlcywgNiwgNykKY3JpbWVfaGlzdG9yeSA8LSBoZWFkKGFzLnZlY3Rvcih0YWJsZSh0cmFpbiRNb250aCx0cmFpbiRZZWFyKSksIC0xMikKY3JpbWVfaGlzdG9yeQpjcmltZV90cyA8LSB0cyhjcmltZV9oaXN0b3J5LCBmcmVxdWVuY3k9MTIsIHN0YXJ0PWMoMjAwMywxKSkKY3JpbWVfdHMgCnBsb3QudHMoY3JpbWVfdHMpCmBgYApXZSBjYW4gc2VlIHRoYXQgdGhlIGJhc2ljIHRyZW5kIGlzIGRlY2xpbmluZyBmcm9tIDIwMDQgdG8gMjAxMC4gVGhlbiwgY3JpbWUgcmF0ZSBiZWdpbnMgdG8gcmlzZSB1bnRpbCAyMDE0LiBCdXQgbm90aWNlYWJseSB3ZSBjYW4gY2xlYXJseSBvYnNlcnZlIHRoZSBzZWFzb25hbGl0eSB0aHJvdWdob3V0IHRoZSB5ZWFycy4gU28gaXQncyB3b3J0aHdoaWxlIHRvIGludmVzdGlnYXRlIHRoZSBmbHVjdHVhdGlvbiBvdmVyIHRoZSBtb250aHMuIE1heWJlIHNvbWUgYW5hbHlzaXMgb3ZlciB0aW1lLWluLWEtZGF5IHdvdWxkIGJlIGhlbHBmdWwgdG9vLiBGb3Igbm93IGxldCdzIGp1c3QgZGVjb21wb3NlIHRoZSBkYXRhLgpgYGB7cn0KY3JpbWVfY29tcG9uZW50cyA8LSBkZWNvbXBvc2UoY3JpbWVfdHMpCnBsb3QoY3JpbWVfY29tcG9uZW50cykKYGBgCkl0IHNlZW1zIHRoZSB0cmVuZCBpcyBqdXN0IHdoYXQgSSBkZXNjcmliZWQsIHJvdWdobHkuIFRoZSBzZWFzb25hbCBjb21wb25lbnQgc2VlbXMgcmVhbGx5IGludGVyZXN0aW5nLgpgYGB7cn0KdHJhaW5faW5jb21wbGV0ZSA8LSBzdWJzZXQodHJhaW4sIFllYXIgIT0gMjAxNSkKdGIgPC0gdGFibGUodHJhaW5faW5jb21wbGV0ZSRNb250aCwgdHJhaW5faW5jb21wbGV0ZSRDYXRlZ29yeSkKZGYgPC0gZGF0YS5mcmFtZShtb250aD1hcy5pbnRlZ2VyKHJvdy5uYW1lcyh0YikpLCBjcmltZV9mcmVxPWFzLnZlY3Rvcih0YiksIGNyaW1lX2NhdGVnb3JpZXM9cmVwKGNvbG5hbWVzKHRiKSwgZWFjaD1sZW5ndGgocm93Lm5hbWVzKHRiKSkpKQojIHBsb3QKZ2dwbG90KGRhdGEgPSBkZiwgYWVzKHg9bW9udGgsIHk9Y3JpbWVfZnJlcSkpICsgZ2VvbV9saW5lKGFlcyhjb2xvdXI9Y3JpbWVfY2F0ZWdvcmllcykpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJsZWZ0IikKYGBgCmBgYHtyfQojIENyZWF0ZSB0aGUgZGF0YSBmb3IgdGhlIGNoYXJ0Lgp0YiA8LSB0YWJsZSh0cmFpbl9pbmNvbXBsZXRlJE1vbnRoLCB0cmFpbl9pbmNvbXBsZXRlJENhdGVnb3J5KQp2ID0gcm93U3Vtcyh0YikKIyBQbG90IHRoZSBiYXIgY2hhcnQuCnBsb3Qodix0eXBlID0gIm8iLCBjb2wgPSAicmVkIiwgeGxhYiA9ICJNb250aCIsIHlsYWIgPSAiQ3JpbWUgRnJlcXVlbmN5IiwKICAgbWFpbiA9ICJNb250aGx5IENyaW1lIikKYGBgCldlIGNhbiBzZWUgdGhhdCwgdXN1YWxseSBEZWNlbWJlciBhbmQgRmVidXJhcnkgaGFzIHRoZSBsb3dlc3QgY3JpbWUgcmF0ZSAocGVyaGFwcyBwZW9wbGUgZmVlbCB0b28gY29sZCB0byBsZWF2ZSBob21lKS4gSnVuZSwgSnVseSwgQXVndXN0IGhhdmUgbG93IGZyZXF1ZW5jeSBhcyB3ZWxsLiBDcmltZSBhY3Rpdml0aWVzIHBlYWsgaW4gTWF5IGFuZCBPY3RvYmVyLiBUaGlzIHBhdHRlcm4gaXMgb2JzZXJ2ZWQgYnkgYWxsIG1ham9yIGNhdGVnb3JpZXMgb2YgY3JpbWUuIApIb3dldmVyLCB0aGUgZGF0YSBvZiBEZWNlbWJlciBpcyBzaWduaWZpY2FudGx5IGxvd2VyIHRoYW4gdGhlIG90aGVycy4gTWF5YmUgaXQncyBiZWNhdXNlIG9mIHRoZSBsYWNrIG9mIGRhdGEgaW4gMjAxNS4gKkknbGwgZ2V0IHJpZCBvZiB0aGUgZGF0YSBvZiAyMDE1IHdoZW4gbmVjZXNzYXJ5IGFuZCBhZGp1c3QgdGhlIHByZXZpb3VzIHJlc3VsdHMuKgoKSnVzdCBhbiBleGFtcGxlIG9mIG1hcHBpbmcgU0YuCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dtYXApCmxpYnJhcnkobWFwdG9vbHMpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkocmdlb3MpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGx5cikKbGlicmFyeShncmlkKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShyZXNoYXBlMikKbGlicmFyeShzY2FsZXMpCgpwbG90VGhlbWUgPC0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTIpIHsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoIGNvbG9yID0gImJsYWNrIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCxjb2xvdXIgPSAiYmxhY2siKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0iaXRhbGljIiksCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MCksCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoImdyZXk4MCIsIHNpemUgPSAwLjEpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJ3aGl0ZSIpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT04KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTgpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0PTEpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGhqdXN0PTEpLAogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIikpCn0KIAojIEFuZCBhbm90aGVyIHRoYXQgd2Ugd2lsbCB1c2UgZm9yIG1hcHMKbWFwVGhlbWUgPC0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTIpIHsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoIGNvbG9yID0gImJsYWNrIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCxjb2xvdXIgPSAiYmxhY2siKSwKICAgIHBsb3Quc3VidGl0bGU9ZWxlbWVudF90ZXh0KGZhY2U9Iml0YWxpYyIpLAogICAgcGxvdC5jYXB0aW9uPWVsZW1lbnRfdGV4dChoanVzdD0wKSwKICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZSgiZ3JleTgwIiwgc2l6ZSA9IDAuMSksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JleTgwIiwgY29sb3IgPSAid2hpdGUiKSwKICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siLCBmYWNlID0gIml0YWxpYyIpKQp9CiAKIyBEZWZpbmUgc29tZSBwYWxldHRlcwpwYWxldHRlXzlfY29sb3JzIDwtIGMoIiMwREEzQTAiLCIjMjk5OUE5IiwiIzQ1OEZCMiIsIiM2Mjg1QkIiLCIjN0U3Q0M0IiwiIzlBNzJDRCIsIiNCNzY4RDYiLCIjRDM1RURGIiwiI0YwNTVFOSIpCnBhbGV0dGVfOF9jb2xvcnMgPC0gYygiIzBEQTNBMCIsIiMyRDk3QUEiLCIjNEQ4Q0I0IiwiIzZFODFCRiIsIiM4RTc2QzkiLCIjQUY2QkQ0IiwiI0NGNjBERSIsIiNGMDU1RTkiKQpwYWxldHRlXzdfY29sb3JzIDwtIGMoIiMyRDk3QUEiLCIjNEQ4Q0I0IiwiIzZFODFCRiIsIiM4RTc2QzkiLCIjQUY2QkQ0IiwiI0NGNjBERSIsIiNGMDU1RTkiKQpwYWxldHRlXzFfY29sb3JzIDwtIGMoIiMwREEzQTAiKQoKCiMgUmVhZCBpbiBhIGNzdiBvZiBob21lIHNhbGUgdHJhbnNhY3Rpb25zIGRpcmVjdGx5IGZyb20gZ2l0aHViLgpzZiA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3NpbW9ua2Fzc2VsL1Zpc3VhbGl6aW5nX1NGX2hvbWVfcHJpY2VzX1IvbWFzdGVyL0RhdGEvU0ZfaG9tZV9zYWxlc19kZW1vX2RhdGEuY3N2IikKIAojIFdlIHdpbGwgbmVlZCB0byBjb25zaWRlciBTYWxlIFllYXIgYXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBzbyB3ZSBjb252ZXJ0IGl0IGZyb20gYSBudW1lcmljIHZhcmlhYmxlIHRvIGEgZmFjdG9yCnNmJFNhbGVZciA8LSBhcy5mYWN0b3Ioc2YkU2FsZVlyKQoKIyBEZWZpbmUgdGhlIFVSTCBvZiB0aGUgemlwcGVkIHNoYXBlZmlsZQpVUkwgPC0gImh0dHBzOi8vZ2l0aHViLmNvbS9zaW1vbmthc3NlbC9WaXN1YWxpemluZ19TRl9ob21lX3ByaWNlc19SL3Jhdy9tYXN0ZXIvRGF0YS9TRl9uZWlnaGJvcmhvb2RzLnppcCIKIyBEb3dubG9hZCB0aGUgc2hhcGVmaWxlIHRvIHlvdXIgd29ya2luZyBkaXJlY3RvcnkgYW5kIHVuemlwIGl0Lgpkb3dubG9hZC5maWxlKFVSTCwgIlNGX25laWdoYm9yaG9vZHMuemlwIikKdW56aXAoIlNGX25laWdoYm9yaG9vZHMuemlwIikKIyBSZWFkIGl0IGludG8gUiBhcyBhIHNwYXRpYWwgcG9seWdvbnMgZGF0YSBmcmFtZSAmIHBsb3QKbmVpZ2hiIDwtIHJlYWRTaGFwZVBvbHkoIlNGX25laWdoYm9yaG9vZHMiKQpwbG90KG5laWdoYikKCgojIERlZmluZSB0aGUgYm91bmRpbmcgYm94CmJib3ggPC0gbmVpZ2hiQGJib3gKCiMgTWFuaXB1bGF0ZSB0aGVzZSB2YWx1ZXMgc2xpZ2h0bHkgc28gdGhhdCB3ZSBnZXQgc29tZSBwYWRkaW5nIG9uIG91ciBiYXNlbWFwIGJldHdlZW4gdGhlIGVkZ2Ugb2YgdGhlIGRhdGEgYW5kIHRoZSBlZGdlIG9mIHRoZSBtYXAKc2ZfYmJveCA8LSBjKGxlZnQgPSBiYm94WzEsIDFdIC0gLjAxLCBib3R0b20gPSBiYm94WzIsIDFdIC0gLjAwNSwgCiAgICAgICAgICAgICByaWdodCA9IGJib3hbMSwgMl0gKyAuMDEsIHRvcCA9IGJib3hbMiwgMl0gKyAuMDA1KQojIERvd25sb2FkIHRoZSBiYXNlbWFwCmJhc2VtYXAgPC0gZ2V0X3N0YW1lbm1hcCgKICBiYm94ID0gc2ZfYmJveCwKICB6b29tID0gMTMsCiAgbWFwdHlwZSA9ICJ0b25lci1saXRlIikKCiMgIyBNYXAgaXQKIyBibU1hcCA8LSBnZ21hcChiYXNlbWFwKSArIG1hcFRoZW1lKCkgKyAKIyAgIGxhYnModGl0bGU9IlNhbiBGcmFuY2lzY28gYmFzZW1hcCIpCiMgYm1NYXAKCiMgRGVmaW5lIHRoZSBib3VuZGluZyBib3gKYmJveCA8LSBuZWlnaGJAYmJveAogCiMgTWFuaXB1bGF0ZSB0aGVzZSB2YWx1ZXMgc2xpZ2h0bHkgc28gdGhhdCB3ZSBnZXQgc29tZSBwYWRkaW5nIG9uIG91ciBiYXNlbWFwIGJldHdlZW4gdGhlIGVkZ2Ugb2YgdGhlIGRhdGEgYW5kIHRoZSBlZGdlIG9mIHRoZSBtYXAKc2ZfYmJveCA8LSBjKGxlZnQgPSBiYm94WzEsIDFdIC0gLjAxLCBib3R0b20gPSBiYm94WzIsIDFdIC0gLjAwNSwgCiAgICAgICAgICAgICByaWdodCA9IGJib3hbMSwgMl0gKyAuMDEsIHRvcCA9IGJib3hbMiwgMl0gKyAuMDA1KQojIERvd25sb2FkIHRoZSBiYXNlbWFwCmJhc2VtYXAgPC0gZ2V0X3N0YW1lbm1hcCgKICBiYm94ID0gc2ZfYmJveCwKICB6b29tID0gMTMsCiAgbWFwdHlwZSA9ICJ0b25lci1saXRlIikKIAojICMgTWFwIGl0CiMgYm1NYXAgPC0gZ2dtYXAoYmFzZW1hcCkgKyBtYXBUaGVtZSgpICsgCiMgICBsYWJzKHRpdGxlPSJTYW4gRnJhbmNpc2NvIGJhc2VtYXAiKQojIGJtTWFwCgojIAojIHByaWNlc19tYXBwZWRfYnlfeWVhciA8LSBnZ21hcChiYXNlbWFwKSArIAojICAgZ2VvbV9wb2ludChkYXRhID0gc2YsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgY29sb3IgPSBTYWxlUHJpY2UpLCAKIyAgICAgICAgICAgICAgc2l6ZSA9IC4yNSwgYWxwaGEgPSAwLjYpICsKIyAgIGZhY2V0X3dyYXAoflNhbGVZciwgc2NhbGVzID0gImZpeGVkIiwgbmNvbCA9IDQpICsKIyAgIGNvb3JkX21hcCgpICsKIyAgIG1hcFRoZW1lKCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKC44NSwgLjI1KSkgKwojICAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKCJTYWxlIFByaWNlIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzID0gcGFsZXR0ZV84X2NvbG9ycywKIyAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcl9mb3JtYXQocHJlZml4ID0gIiQiKSkgKwojICAgbGFicyh0aXRsZT0iRGlzdHJpYnV0aW9uIG9mIFNhbiBGcmFuY2lzY28gaG9tZSBwcmljZXMiLAojICAgICAgICBzdWJ0aXRsZT0iTm9taW5hbCBwcmljZXMgKDIwMDkgLSAyMDE1KSIsCiMgICAgICAgIGNhcHRpb249IlNvdXJjZTogU2FuIEZyYW5jaXNjbyBPZmZpY2Ugb2YgdGhlIEFzc2Vzc29yLVJlY29yZGVyXG5AS2VuU3RlaWYgJiBAU2ltb25LYXNzZWwiKQojIHByaWNlc19tYXBwZWRfYnlfeWVhcgpgYGAKYGBge3J9CnRyYWluWywgYygiWCIsICJZIiwgIlllYXIiLCAiQ2F0ZWdvcnkiKV0KY3JpbWVfbG9jYXRpb24gPC0gZGF0YS5mcmFtZSggdHJhaW5bLCBjKCJYIiwgIlkiLCAiWWVhciIsICJDYXRlZ29yeSIpXSApCmNyaW1lX2xvY2F0aW9uCmBgYApgYGB7cn0KIyBNYW5pcHVsYXRlIHRoZXNlIHZhbHVlcyBzbGlnaHRseSBzbyB0aGF0IHdlIGdldCBzb21lIHBhZGRpbmcgb24gb3VyIGJhc2VtYXAgYmV0d2VlbiB0aGUgZWRnZSBvZiB0aGUgZGF0YSBhbmQgdGhlIGVkZ2Ugb2YgdGhlIG1hcApzZl9iYm94IDwtIGMobGVmdCA9IGJib3hbMSwgMV0gLSAuMDEsIGJvdHRvbSA9IGJib3hbMiwgMV0gLSAuMDA1LCAKICAgICAgICAgcmlnaHQgPSBiYm94WzEsIDJdICsgLjAxLCB0b3AgPSBiYm94WzIsIDJdICsgLjAwNSkKIyBEb3dubG9hZCB0aGUgYmFzZW1hcApiYXNlbWFwIDwtIGdldF9zdGFtZW5tYXAoCiAgYmJveCA9IHNmX2Jib3gsCiAgem9vbSA9IDEzLAogIG1hcHR5cGUgPSAidG9uZXItbGl0ZSIpCiAKIyBNYXAgaXQKYm1NYXAgPC0gZ2dtYXAoYmFzZW1hcCkgKyBtYXBUaGVtZSgpICsgCiAgbGFicyh0aXRsZT0iU2FuIEZyYW5jaXNjbyBDcmltZSBNYXAiKQpibU1hcCArIGdlb21fcG9pbnQoZGF0YT1jcmltZV9sb2NhdGlvbiwgYWVzKHg9WCwgeT1ZLCBjb2xvcj1DYXRlZ29yeSksIHNpemU9MC43LCBhbHBoYT0wLjMpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpgYGB7cn0KdG9wX2NyaW1lX21hcCA8LSBjcmltZV9sb2NhdGlvbltjcmltZV9sb2NhdGlvbiRDYXRlZ29yeSAlaW4lIGFzLnZlY3Rvcih0b3BfY3JpbWVzJFZhcjEpLF0KYm1NYXBUb3AgPC0gZ2dtYXAoYmFzZW1hcCkgKyBtYXBUaGVtZSgpICsgCiAgbGFicyh0aXRsZT0iU2FuIEZyYW5jaXNjbyBUb3AgQ3JpbWUgTWFwIikKYm1NYXBUb3AgKyBnZW9tX3BvaW50KGRhdGE9dG9wX2NyaW1lX21hcCwgYWVzKHg9WCwgeT1ZLCBjb2xvcj1DYXRlZ29yeSksIHNpemU9MC43LCBhbHBoYT0wLjMpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCkFsdGhvdWdoIHRoaXMgbWFwIGlzIGJlYXV0aWZ1bCwgaXQgcHJvdmlkZXMgdXMgd2l0aCB0b28gbXVjaCBpbmZvcm1hdGlvbiB0byBiZSBpbnNpZ2h0ZnVsLiBUbyBnZXQgbW9yZSBvdXQgb2YgdGhpcyB2aXN1YWxpc2F0aW9uLCB3ZSBuZWVkIHRvIGxpbWl0IHRoZSBjYXRlZ29yaWVzIHRvIHRob3NlIG1vc3QgJ3BvcHVsYXInIGNyaW1lcywgb3Igd2UgbmVlZCB0byByZWdyb3VwIHRoZSBjcmltZSBjYXRlZ29yaWVzLgpgYGB7cn0KIyBNYXAgaXQKYm1NYXAgPC0gZ2dtYXAoYmFzZW1hcCkgKyBtYXBUaGVtZSgpICsgCiAgbGFicyh0aXRsZT0iU2FuIEZyYW5jaXNjbyBiYXNlbWFwIikKCnByaWNlc19tYXBwZWRfYnlfeWVhciA8LSBnZ21hcChiYXNlbWFwKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IHRvcF9jcmltZV9tYXAsIGFlcyh4ID0gWCwgeSA9IFksIGNvbG9yID0gQ2F0ZWdvcnkpLCAKICAgICAgICAgICAgIHNpemUgPSAuMjUsIGFscGhhID0gMC42KSArCiAgZmFjZXRfd3JhcCh+WWVhciwgc2NhbGVzID0gImZpeGVkIiwgbmNvbCA9IDQpICsKICBjb29yZF9tYXAoKSArCiAgbWFwVGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsKICBsYWJzKHRpdGxlPSJUb3AgMTAgQ3JpbWVzIGluIFNhbiBGcmFuY2lzY28iLAogICAgICAgc3VidGl0bGU9IjIwMDMgLSAyMDE1IikKcHJpY2VzX21hcHBlZF9ieV95ZWFyCmBgYApPayBhbnl3YXlzLi4uIFRoYW5rcyB0byBLZWx2aW4sIEkgbm90aWNlZCB0aGVyZSBpcyBhIHZlcnkgc3Ryb25nIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIERlc2NyaXRpb24gY29sdW1uIGFuZCB0aGUgQ2F0ZWdvcnkgY29sdW1uLiBTb21lIHRleHQgbWluaW5nIGlzIG5lZWRlZCB0aG91Z2guCmBgYHtyfQojdHJhaW4kRGVzY3JpcHQKbGlicmFyeSh0bSkKbGlicmFyeSh3b3JkY2xvdWQpCmRlc2NyaXB0IDwtIHJlbW92ZU51bWJlcnMocmVtb3ZlUHVuY3R1YXRpb24odG9sb3dlcihhcy52ZWN0b3IodHJhaW4kRGVzY3JpcHQpKSkpIApkZXNjcmlwdCA8LSByZW1vdmVXb3JkcyhkZXNjcmlwdCwgc3RvcHdvcmRzKCJlbiIpKQpkZXNjcmlwdF9jb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0cmFpbiREZXNjcmlwdCkpCmRlc2NyaXB0X2NvcnB1cyA9IHRtX21hcChkZXNjcmlwdF9jb3JwdXMsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpCmRlc2NyaXB0X2NvcnB1cyA9IHRtX21hcChkZXNjcmlwdF9jb3JwdXMsIHJlbW92ZU51bWJlcnMpCmRlc2NyaXB0X2NvcnB1cyA9IHRtX21hcChkZXNjcmlwdF9jb3JwdXMsIHJlbW92ZVB1bmN0dWF0aW9uKQpkZXNjcmlwdF9jb3JwdXMgPSB0bV9tYXAoZGVzY3JpcHRfY29ycHVzLCByZW1vdmVXb3JkcywgYygidGhlIiwgImFuZCIpKQpkZXNjcmlwdF9jb3JwdXMgPSAgdG1fbWFwKGRlc2NyaXB0X2NvcnB1cywgc3RyaXBXaGl0ZXNwYWNlKQpkZXNjcmlwdF9kdG0gPC0gRG9jdW1lbnRUZXJtTWF0cml4KGRlc2NyaXB0X2NvcnB1cykKZGVzY3JpcHRfZHRtIDwtIHJlbW92ZVNwYXJzZVRlcm1zKGRlc2NyaXB0X2R0bSwgMC45NzUpCmZpbmRGcmVxVGVybXMoZGVzY3JpcHRfZHRtLCAxMDApCnJhd19mcmVxID0gZGF0YS5mcmFtZShzb3J0KGNvbFN1bXMoYXMubWF0cml4KGRlc2NyaXB0X2R0bSkpLCBkZWNyZWFzaW5nPVRSVUUpKQpyYXdfZnJlcQpkaW0ocmF3X2ZyZXEpCmZyZXFfd29yZHMgPC0gcm93bmFtZXMocmF3X2ZyZXEpCmZyZXFfd29yZHMKd29yZGNsb3VkKHJvd25hbWVzKHJhd19mcmVxKSwgcmF3X2ZyZXFbLDFdLCBtYXgud29yZHM9MTAwLCBjb2xvcnM9YnJld2VyLnBhbCgxLCAiRGFyazIiKSkKYGBgCmBgYHtyfQpkZXNjcmlwdF9kdG1fdGZpZGYgPC0gRG9jdW1lbnRUZXJtTWF0cml4KGRlc2NyaXB0X2NvcnB1cywgY29udHJvbCA9IGxpc3Qod2VpZ2h0aW5nID0gd2VpZ2h0VGZJZGYpKQpkZXNjcmlwdF9kdG1fdGZpZGYgPSByZW1vdmVTcGFyc2VUZXJtcyhkZXNjcmlwdF9kdG1fdGZpZGYsIDAuOTc1KQpmcmVxID0gZGF0YS5mcmFtZShzb3J0KGNvbFN1bXMoYXMubWF0cml4KGRlc2NyaXB0X2R0bV90ZmlkZikpLCBkZWNyZWFzaW5nPVRSVUUpKQpmcmVxCmZyZXFfd29yZHMgPC0gYyhmcmVxX3dvcmRzLCByb3duYW1lcyhmcmVxKSkKZnJlcV93b3JkcyA8LSB1bmlxdWUoZnJlcV93b3JkcykKZnJlcV93b3Jkcwp3b3JkY2xvdWQocm93bmFtZXMoZnJlcSksIGZyZXFbLDFdLCBtYXgud29yZHM9MTAwLCBjb2xvcnM9YnJld2VyLnBhbCgxLCAiRGFyazIiKSkKYGBgCk9rLCBsZXQncyB0cnkgdG8gc2VhcmNoIGZvciBzb21lICprZXl3b3JkcyogaW4gdGhlIGRlc2NyaXB0IGNvbHVtbiB0aGF0IG1hdGNoZXMgdGhlIGNhdGVnb3J5IGNvbHVtbi4KYGBge3J9CnVuaXF1ZV9jYXQgPC0gdW5pcXVlKHRyYWluJENhdGVnb3J5KQp4IDwtICIiCmZvcihjYXQgaW4gdW5pcXVlKHRyYWluJENhdGVnb3J5KSkgewogIHggPC0gcGFzdGUoeCwgY2F0LCBzZXA9InwiKQp9CnggPC0gdG9sb3dlcihzdWJzdHJpbmcoeCwyKSkgCm1hdGNoX2NvdW50X3RhYmxlIDwtIHRhYmxlKGdyZXBsKHgsIHRvbG93ZXIodHJhaW4kRGVzY3JpcHQpKSkKbWF0Y2hfY291bnRfdGFibGUKcHJvcC50YWJsZShtYXRjaF9jb3VudF90YWJsZSkKYGBgClNvIGFib3V0IDIwJSBvZiB0aGUgREVTQ1JJUFQgY29udGFpbnMgdGhlIENBVEVHT1JZIGtleXdvcmRzLiAqKlRoZXJlIGlzIGEgcmF0aGVyIHN0cm9uZyBjb3JyZWxhdGlvbiBpbmRlZWQuIFRoaXMgaXMgZGVmaW5pdGVseSBnb2luZyB0byBiZSBhIGZlYXR1cmUuKioKSG93IGFib3V0IHRoZSAqKmhvbGlkYXlzKio/IExldCdzIGdldCBzb21lIGRhdGEgYWJvdXQgdGhlIHB1YmxpYyBob2xpZGF5IGluIFNhbiBGcmFuY2lzY28hISEKYGBge3J9CnJlZ3VsYXJfZGF5IDwtIHRyYWluCnRyYWluJEhvbGlkYXkgPC0gIlJlZ3VsYXIiCiMgSG9saWRheXMgCm5ld195ZWFyIDwtIHJlZ3VsYXJfZGF5W2dyZXBsKCJbMC05XXs0fS0wMS0wMSIsIHJlZ3VsYXJfZGF5JERhdGVzKSxdCnRyYWluJEhvbGlkYXlbZ3JlcGwoIlswLTldezR9LTAxLTAxIiwgdHJhaW4kRGF0ZXMpXSA8LSAiTmV3WWVhciIKcmVndWxhcl9kYXkgPC0gcmVndWxhcl9kYXlbIWdyZXBsKCJbMC05XXs0fS0wMS0wMSIsIHJlZ3VsYXJfZGF5JERhdGVzKSxdCiNWYWxlbnRpbmUKdmFsZW50aW5lIDwtIHJlZ3VsYXJfZGF5W2dyZXBsKCJbMC05XXs0fS0wMi0xNCIsIHJlZ3VsYXJfZGF5JERhdGVzKSxdCnRyYWluJEhvbGlkYXlbZ3JlcGwoIlswLTldezR9LTAyLTE0IiwgdHJhaW4kRGF0ZXMpXSA8LSAiVmFsZW50aW5lIgpyZWd1bGFyX2RheSA8LSByZWd1bGFyX2RheVshZ3JlcGwoIlswLTldezR9LTAyLTE0IiwgcmVndWxhcl9kYXkkRGF0ZXMpLF0KI01MSyA8LSAjIFRoaXJkIE1vbmRheSBpbiBKYW51YXJ5CiNwcmVzaWRlbnRzX2RheSA8LSAjIFRoaXJkIE1vbmRheSBpbiBGZWJyYXJ5CiNlYXN0ZXIgPC0gIyBBcnIKI21lbW9yaWFsX2RheSA8LSAjIExhc3QgTW9uZGF5IGluIE1heQppbmRlcGVuZGVuY2VfZGF5IDwtIHJlZ3VsYXJfZGF5W2dyZXBsKCJbMC05XXs0fS0wNy0wNCIsIHJlZ3VsYXJfZGF5JERhdGVzKSxdCnRyYWluJEhvbGlkYXlbZ3JlcGwoIlswLTldezR9LTA3LTA0IiwgdHJhaW4kRGF0ZXMpXSA8LSAiSW5kZXBlbmRlbmNlIgpyZWd1bGFyX2RheSA8LSByZWd1bGFyX2RheVshZ3JlcGwoIlswLTldezR9LTA3LTA0IiwgcmVndWxhcl9kYXkkRGF0ZXMpLF0KI2xhYm9yX2RheSA8LSAjIEZpcnN0IE1vbmRheSBpbiBTZXB0ZW1iZXIgCiNjb2x1bWJ1c19kYXkgPC0gIyBTZWNvbmQgTW9uZGF5IGluIE9jdG9iZXIKdmV0ZXJhbnNfZGF5IDwtIHJlZ3VsYXJfZGF5W2dyZXBsKCJbMC05XXs0fS0xMS0xMSIsIHJlZ3VsYXJfZGF5JERhdGVzKSxdCnRyYWluJEhvbGlkYXlbZ3JlcGwoIlswLTldezR9LTExLTExIiwgdHJhaW4kRGF0ZXMpXSA8LSAiVmV0ZXJhbnMiCnJlZ3VsYXJfZGF5IDwtIHJlZ3VsYXJfZGF5WyFncmVwbCgiWzAtOV17NH0tMTEtMTEiLCByZWd1bGFyX2RheSREYXRlcyksXQojdGhhbmtzX2dpdmluZyA8LSAjICBGb3VydGggVGh1cnNkYXkgaW4gTm92ZW1iZXIKY2hyaXN0bWFzIDwtIHJlZ3VsYXJfZGF5W2dyZXBsKCJbMC05XXs0fS0xMi0yNSIsIHJlZ3VsYXJfZGF5JERhdGVzKSxdCnRyYWluJEhvbGlkYXlbZ3JlcGwoIlswLTldezR9LTEyLTI1IiwgdHJhaW4kRGF0ZXMpXSA8LSAiQ2hyaXN0bWFzIgpyZWd1bGFyX2RheSA8LSByZWd1bGFyX2RheVshZ3JlcGwoIlswLTldezR9LTEyLTI1IiwgcmVndWxhcl9kYXkkRGF0ZXMpLF0KYGBgCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCm5ld195ZWFyX3RvcF9jcmltZSA8LSBuZXdfeWVhcltuZXdfeWVhciRDYXRlZ29yeSAlaW4lIGFzLnZlY3Rvcih0b3BfY3JpbWVzJFZhcjEpLF0KZyA8LSBnZ3Bsb3QobmV3X3llYXJfdG9wX2NyaW1lLCBhZXMoWWVhcikpCmcgKyBnZW9tX2JhcigpICsgZ2VvbV9iYXIoYWVzKGZpbGw9Q2F0ZWdvcnkpKSArIGdndGl0bGUoIk5ldyBZZWFyIENyaW1lIikKYGBgCgpgYGB7cn0KaW5kX3RvcF9jcmltZSA8LSBpbmRlcGVuZGVuY2VfZGF5W2luZGVwZW5kZW5jZV9kYXkkQ2F0ZWdvcnkgJWluJSBhcy52ZWN0b3IodG9wX2NyaW1lcyRWYXIxKSxdCmcgPC0gZ2dwbG90KGluZF90b3BfY3JpbWUsIGFlcyhZZWFyKSkKZyArIGdlb21fYmFyKCkgKyBnZW9tX2JhcihhZXMoZmlsbD1DYXRlZ29yeSkpICsgZ2d0aXRsZSgiSW5kZXBlbmRlbmNlIERheSBDcmltZSIpCmBgYApgYGB7cn0KdmV0ZXJhbnNfdG9wX2NyaW1lIDwtIHZldGVyYW5zX2RheVt2ZXRlcmFuc19kYXkkQ2F0ZWdvcnkgJWluJSBhcy52ZWN0b3IodG9wX2NyaW1lcyRWYXIxKSxdCmcgPC0gZ2dwbG90KHZldGVyYW5zX3RvcF9jcmltZSwgYWVzKFllYXIpKQpnICsgZ2VvbV9iYXIoKSArIGdlb21fYmFyKGFlcyhmaWxsPUNhdGVnb3J5KSkgKyBnZ3RpdGxlKCJWZXRlcmFucyBEYXkgQ3JpbWUiKQpgYGAKCmBgYHtyfQpjaHJpc3RtYXNfdG9wX2NyaW1lIDwtIGNocmlzdG1hc1tjaHJpc3RtYXMkQ2F0ZWdvcnkgJWluJSBhcy52ZWN0b3IodG9wX2NyaW1lcyRWYXIxKSxdCmcgPC0gZ2dwbG90KGNocmlzdG1hc190b3BfY3JpbWUsIGFlcyhZZWFyKSkKZyArIGdlb21fYmFyKCkgKyBnZW9tX2JhcihhZXMoZmlsbD1DYXRlZ29yeSkpICsgZ2d0aXRsZSgiQ2hyaXN0bWFzIENyaW1lIikKYGBgClRpbWUgdG8gZG8gc29tZSBhdmVyYWdpbmcuLi4KYGBge3J9CmxpYnJhcnkobWF0cml4U3RhdHMpCm5ld195ZWFyX2F2ZyA8LSBjb2xNZWRpYW5zKHRhYmxlKG5ld195ZWFyX3RvcF9jcmltZSRZZWFyLCBkcm9wbGV2ZWxzKG5ld195ZWFyX3RvcF9jcmltZSRDYXRlZ29yeSkpKSAKdmFsZW50aW5lX3RvcF9jcmltZSA8LSB2YWxlbnRpbmVbdmFsZW50aW5lJENhdGVnb3J5ICVpbiUgYXMudmVjdG9yKHRvcF9jcmltZXMkVmFyMSksXQp2YWxlbnRpbmVfYXZnIDwtIGNvbE1lZGlhbnModGFibGUodmFsZW50aW5lX3RvcF9jcmltZSRZZWFyLCBkcm9wbGV2ZWxzKHZhbGVudGluZV90b3BfY3JpbWUkQ2F0ZWdvcnkpKSkgCmluZF9kYXlfYXZnIDwtIGNvbE1lZGlhbnModGFibGUoaW5kX3RvcF9jcmltZSRZZWFyLCBkcm9wbGV2ZWxzKGluZF90b3BfY3JpbWUkQ2F0ZWdvcnkpKSkKdmV0ZXJhbnNfYXZnIDwtIGNvbE1lZGlhbnModGFibGUodmV0ZXJhbnNfdG9wX2NyaW1lJFllYXIsIGRyb3BsZXZlbHModmV0ZXJhbnNfdG9wX2NyaW1lJENhdGVnb3J5KSkpCmNocmlzdG1hc19hdmcgPC0gY29sTWVkaWFucyh0YWJsZShjaHJpc3RtYXNfdG9wX2NyaW1lJFllYXIsIGRyb3BsZXZlbHMoY2hyaXN0bWFzX3RvcF9jcmltZSRDYXRlZ29yeSkpKQpyZWdfZGF5X3RvcF9jcmltZSA8LSByZWd1bGFyX2RheVtyZWd1bGFyX2RheSRDYXRlZ29yeSAlaW4lIGFzLnZlY3Rvcih0b3BfY3JpbWVzJFZhcjEpLF0KcmVnX2RheV90b3BfY3JpbWUkRGF0ZU9ubHkgPC0gc3Vic3RyaW5nKHJlZ19kYXlfdG9wX2NyaW1lJERhdGVzLCAxLCAxMCkKI3JlZ19kYXlfdG9wX2NyaW1lJERhdGVPbmx5CnJlZ19kYXlfYXZnIDwtIGNvbE1lZGlhbnModGFibGUocmVnX2RheV90b3BfY3JpbWUkRGF0ZU9ubHksIGRyb3BsZXZlbHMocmVnX2RheV90b3BfY3JpbWUkQ2F0ZWdvcnkpKSkKI3JlZ19kYXlfYXZnCmBgYApgYGB7cn0KaG9saWRheV9jb21wYXJpc29uX2RmIDwtIGRhdGEuZnJhbWUoTmV3WWVhcj1uZXdfeWVhcl9hdmcsIFZhbGVudGluZSA9IHZhbGVudGluZV9hdmcsIEluZD1pbmRfZGF5X2F2ZywgVmV0ZXJhbnM9dmV0ZXJhbnNfYXZnLCBDaHJpc3RtYXM9Y2hyaXN0bWFzX2F2ZywgUmVndWxhcj1yZWdfZGF5X2F2ZykKcm93Lm5hbWVzKGhvbGlkYXlfY29tcGFyaXNvbl9kZikgPC0gc29ydCh0b3BfY3JpbWVzJFZhcjEpCmhvbGlkYXlfY29tcGFyaXNvbl9kZgpgYGAKYGBge3J9CnBhcih4cGQ9VFJVRSkKYmFycGxvdChhcy5tYXRyaXgoaG9saWRheV9jb21wYXJpc29uX2RmKSwgbWFpbj0iQ3JpbWVzIGluIFNwZWNpYWwgRGF5cyIsIGNvbD1yYWluYm93KG5yb3coaG9saWRheV9jb21wYXJpc29uX2RmKSksIHhsYWI9IlNwZWNpYWwgRGF5cyIsIGJ0eT0nTCcpCmxlZ2VuZCgidG9wcmlnaHQiLAogICAgICAgbGVnZW5kID0gc29ydCh0b3BfY3JpbWVzJFZhcjEpLCAKICAgICAgIGZpbGwgPSByYWluYm93KG5yb3coaG9saWRheV9jb21wYXJpc29uX2RmKSksIGNleD0wLjQpCmBgYApMZXQncyBzZWUgaG93IHRoZSBwbG90IHZhcmllcyB0aHJvdWdob3V0IHRoZSAyNCBob3VycyBpbiBhIGRheToKYGBge3J9CmNyaW1lX3RpbWVfZGYgPC0gZGF0YS5mcmFtZShUaW1lPWFzLlBPU0lYY3Qoc3Vic3RyaW5nKHRyYWluJERhdGVzLDEyKSwgZm9ybWF0PSIlSDolTTolUyIpLCBDYXRlZ29yeT10cmFpbiRDYXRlZ29yeSkKI2dncGxvdChkYXRhPWNyaW1lX3RpbWVfZGYsIGFlcyh4PWNyaW1lX3RpbWVfZGYkVGltZSwgeT0pKSArIGdlb21fcG9pbnQoKQpgYGAKTGV0J3Mgc2VlIGlmIHdlZWtlbmRzIGhhdmUgbW9yZSBjcmltZXMgdGhhbiB3ZWVrZGF5cy4KYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKd2tkYXkgPC0gdHJhaW4Kd2tkYXkkV2VlayA8LSAiV2Vla2RheSIKd2tkYXlbd2tkYXkkRGF5T2ZXZWVrID09ICJTYXR1cmRheSIgfCB3a2RheSREYXlPZldlZWsgPT0gIlN1bmRheSIsXSRXZWVrIDwtICJXZWVrZW5kIgoKd2tkYXlfZGYgPC0gKGRhdGEuZnJhbWUoV2Vlaz13a2RheSRXZWVrLCBDYXRlZ29yeT13a2RheSRDYXRlZ29yeSkpCndrZGF5X2RmCmcgPC0gZ2dwbG90KHdrZGF5X2RmLCBhZXMoV2VlaykpCmcgKyBnZW9tX2JhcigpICsgZ2VvbV9iYXIoYWVzKGZpbGw9Q2F0ZWdvcnkpKSArIGdndGl0bGUoIldlZWtkYXkgdnMuIFdlZWtlbmQiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEpKQoKd2tkYXlfdG9wX2NyaW1lIDwtIHdrZGF5CndrX3RhYmxlIDwtIHRhYmxlKHdrZGF5X3RvcF9jcmltZSRXZWVrKQojd2tkYXlfcmVzdWx0IDwtIGRhdGEuZnJhbWUoV2Vla2RheT10YWJsZSh3a2RheV90b3BfY3JpbWUkQ2F0ZWdvcnksIHdrZGF5X3RvcF9jcmltZSRXZWVrKVssMV0vd2tfdGFibGVbIldlZWtkYXkiXSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgV2Vla2VuZD10YWJsZSh3a2RheV90b3BfY3JpbWUkQ2F0ZWdvcnksIHdrZGF5X3RvcF9jcmltZSRXZWVrKVssMl0vd2tfdGFibGVbIldlZWtlbmQiXSkKd2tkYXlfcmVzdWx0IDwtIGRhdGEuZnJhbWUoV2Vla2RheT10YWJsZSh3a2RheV90b3BfY3JpbWUkQ2F0ZWdvcnksIHdrZGF5X3RvcF9jcmltZSRXZWVrKVssMV0vNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgV2Vla2VuZD10YWJsZSh3a2RheV90b3BfY3JpbWUkQ2F0ZWdvcnksIHdrZGF5X3RvcF9jcmltZSRXZWVrKVssMl0vMikKICAgICAKd2tkYXlfcmVzdWx0CmcgKyB0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikKcGFyKHhwZD1UUlVFKQpiYXJwbG90KGFzLm1hdHJpeCh3a2RheV9yZXN1bHQpLCBtYWluPSJXZWVrZGF5cyB2cy4gV2Vla2VuZHMiLCBjb2w9cmFpbmJvdyhucm93KHdrZGF5X3Jlc3VsdCkpLCB4bGFiPSJEYXkgb2YgV2VlayIsIGJ0eT0nTCcpCmxlZ2VuZCgidG9wcmlnaHQiLAogICAgICAgbGVnZW5kID0gc29ydCh0b3BfY3JpbWVzJFZhcjEpLCAKICAgICAgIGZpbGwgPSByYWluYm93KG5yb3cod2tkYXlfcmVzdWx0KSksIGNleD0wLjQpCmBgYApJdCBzZWVtcyB0aGF0IHdoZXRoZXIgYSBkYXkgaXMgYSB3ZWVrZGF5IG9yIGEgd2Vla2VuZCBkb2Vzbid0IGFmZmVjdCBib3RoIHRoZSBjYXRlZ29yeSBhbmQgdGhlIHF1YW50aXR5IG9mIGNyaW1lcy4uLlNvIGNyaW1pbmFscyBkb2Vzbid0IGhhdmUgZGF5LW9mZnMhIFNBRCEKVW1tIGNvbW1vbiBzZW5zZSB0ZWxscyBtZSB0aGF0IG1vcmUgY3JpbWVzIHRha2UgcGxhY2UgYXQgbmlnaHQgdGhhbiBkdXJpbmcgdGhlIGRheS4gTGV0J3MgZGl2aWRlIHRoZSB0aW1lIGludG8gZGF5IGFuZCBuaWdodCEKYGBge3J9CmxpYnJhcnkoY2hyb24pCnRyYWluJFRpbWUgPC0gdGltZXMoc3Vic3RyaW5nKHRyYWluJERhdGVzLDEyKSkKZGF5TmlnaHQgPC0gZGF0YS5mcmFtZShUaW1lcyA9IHRpbWVzKHN1YnN0cmluZyh0cmFpbiREYXRlcywxMikpLCBDYXQgPSB0cmFpbiRDYXRlZ29yeSkKYnJlYWtzIDwtIGMoMCw2LDEwLDE0LDE4LDI0KS8yNApsYWJlbHMgPC0gYygiRWFybHlNb3JuaW5nIiwiTW9ybmluZyIsIk5vb24iLCJBZnRlcm5vb24iLCJFdmVuaW5nIikKZGF5TmlnaHQkaW5kIDwtIGN1dChkYXlOaWdodCRUaW1lcywgYnJlYWtzLCBsYWJlbHMsIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkKdHJhaW4kVGltZUluRGF5IDwtIGN1dCh0cmFpbiRUaW1lLCBicmVha3MsIGxhYmVscywgaW5jbHVkZS5sb3dlc3QgPSBUKQpkYXlOaWdodApnIDwtIGdncGxvdChkYXlOaWdodCwgYWVzKGluZCkpCmcgKyBnZW9tX2JhcigpICsgZ2VvbV9iYXIoYWVzKGZpbGw9Q2F0KSkgKyBnZ3RpdGxlKCJDcmltZSBpbiBhIGRheSIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsaGp1c3Q9MSkpCmBgYApgYGB7cn0KZGF5TmlnaHQgPC0gZGF0YS5mcmFtZShUaW1lcyA9IHRpbWVzKHN1YnN0cmluZyh0cmFpbiREYXRlcywxMikpLCBDYXQgPSB0cmFpbiRDYXRlZ29yeSkKYnJlYWtzIDwtIGMoMCw1LCAyMCwgMjQpLzI0CmxhYmVscyA8LSBjKCJOaWdodCIsIkRheSIsIk5pZ2h0MiIpCmRheU5pZ2h0JGluZCA8LSBjdXQoZGF5TmlnaHQkVGltZXMsIGJyZWFrcywgbGFiZWxzLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpCnRyYWluJERheU5pZ2h0IDwtIGN1dCh0cmFpbiRUaW1lLCBicmVha3MsIGxhYmVscywgaW5jbHVkZS5sb3dlc3QgPSBUKQpkYXlOaWdodCRpbmQgPC0gZ3N1YigiTmlnaHQyIiwgIk5pZ2h0IiwgZGF5TmlnaHQkaW5kKQp0cmFpbiREYXlOaWdodCA8LSBnc3ViKCJOaWdodDIiLCAiTmlnaHQiLCB0cmFpbiREYXlOaWdodCkKZyA8LSBnZ3Bsb3QoZGF5TmlnaHQsIGFlcyhpbmQpKQpnICsgZ2VvbV9iYXIoKSArIGdlb21fYmFyKGFlcyhmaWxsPUNhdCkpICsgZ2d0aXRsZSgiQ3JpbWUgaW4gYSBkYXkiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEpKQpgYGAKCkFsc28sIG1heWJlIGNyaW1lcyBhcmUgY29ycmVsYXRlZCB3aXRoIHNlYXNvbnM/IExldCdzIGNoZWNrIGl0IG91dCEgQnV0IGFnYWluLCB0aGUgaW5jb21wbGV0ZW5lc3Mgb2YgdGhlIGRhdGEgY2F1c2VzIHVzIGEgbG90IG9mIHRyb3VibGUgYW5kIG1pZ2h0IGxlYWQgdG8gaW5hY2N1cmFjaWVzLCBzbyBzb21lIHNvcnQgb2YgYXZlcmFnaW5nIGlzIG5lZWRlZC4KYGBge3J9CnNlYXNvbnMgPC0gdHJhaW4KIyBNYXJjaCwgQXByaWwsIE1heSA8PT4gU3ByaW5nCnNlYXNvbnMkU2Vhc29uIDwtICJTcHJpbmciCnRyYWluJFNlYXNvbiA8LSAiU3ByaW5nIgojIEp1bmUsIEp1bHksIEF1Z3VzdCA8PT4gU3VtbWVyCnNlYXNvbnNbc2Vhc29ucyRNb250aCA9PSAiMDYiIHwgc2Vhc29ucyRNb250aCA9PSAiMDciIHwgc2Vhc29ucyRNb250aCA9PSAiMDgiLF0kU2Vhc29uIDwtICJTdW1tZXIiCnRyYWluW3RyYWluJE1vbnRoID09ICIwNiIgfCB0cmFpbiRNb250aCA9PSAiMDciIHwgdHJhaW4kTW9udGggPT0gIjA4IixdJFNlYXNvbiA8LSAiU3VtbWVyIgojIFNlcHRlbWJlciwgT2N0b2JlciwgTm92ZW1iZXIgPD0+IEZhbGwKc2Vhc29uc1tzZWFzb25zJE1vbnRoID09ICIwOSIgfCBzZWFzb25zJE1vbnRoID09ICIxMCIgfCBzZWFzb25zJE1vbnRoID09ICIxMSIsXSRTZWFzb24gPC0gIkZhbGwiCnRyYWluW3RyYWluJE1vbnRoID09ICIwOSIgfCB0cmFpbiRNb250aCA9PSAiMTAiIHwgdHJhaW4kTW9udGggPT0gIjExIixdJFNlYXNvbiA8LSAiRmFsbCIKIyBEZWNlbWJlciwgSmFudWFyeSwgRmVicnVhcnkgPD0+IFdpbnRlcgpzZWFzb25zW3NlYXNvbnMkTW9udGggPT0gIjEyIiB8IHNlYXNvbnMkTW9udGggPT0gIjAxIiB8IHNlYXNvbnMkTW9udGggPT0gIjAyIixdJFNlYXNvbiA8LSAiV2ludGVyIgp0cmFpblt0cmFpbiRNb250aCA9PSAiMTIiIHwgdHJhaW4kTW9udGggPT0gIjAxIiB8IHRyYWluJE1vbnRoID09ICIwMiIsXSRTZWFzb24gPC0gIldpbnRlciIKc2Vhc29uX2RmIDwtIChkYXRhLmZyYW1lKFNlYXNvbj1zZWFzb25zJFNlYXNvbiwgQ2F0ZWdvcnk9c2Vhc29ucyRDYXRlZ29yeSkpCmcgPC0gZ2dwbG90KHNlYXNvbl9kZiwgYWVzKFNlYXNvbikpCmcgKyBnZW9tX2JhcigpICsgZ2VvbV9iYXIoYWVzKGZpbGw9Q2F0ZWdvcnkpKSArIGdndGl0bGUoIkNyaW1lIGJ5IFNlYXNvbiIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsaGp1c3Q9MSkpCmBgYApQZERpc3RyaWN0IGlzIHN0aWxsIHVuY2hlY2tlZC4KYGBge3J9CmFyZWFfZGYgPC0gKGRhdGEuZnJhbWUoRGlzdHJpY3Q9dHJhaW4kUGREaXN0cmljdCwgQ2F0ZWdvcnk9dHJhaW4kQ2F0ZWdvcnkpKQphcmVhX2RmCmcgPC0gZ2dwbG90KGFyZWFfZGYsIGFlcyhEaXN0cmljdCkpCmcgKyBnZW9tX2JhcigpICsgZ2VvbV9iYXIoYWVzKGZpbGw9Q2F0ZWdvcnkpKSArIGdndGl0bGUoIkNyaW1lIGJ5IERpc3RyaWN0IikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCxoanVzdD0xKSkKYGBgCkxldCdzIGRvIHNvbWUgdGV4dCBtaW5pbmcgYXMgdGhpcyBpcyBieSBmYXIgdGhlIG1vc3QgdXNlZnVsIGluZm9ybWF0aW9uIQpGaXJzdCwgZGVhbCB3aXRoIHN5bm9ueW1zIG9mIHRoZSBjYXRzCmBgYHtyfQp0cmFpbiRLZXl3b3JkIDwtIE5BCmxpYnJhcnkoInhsc3giKQpsaWJyYXJ5KCJ3b3JkbmV0IikKI3NldERpY3QoIi91c3IvbG9jYWwvQ2VsbGFyL3dvcmRuZXQvMy4xIikKI2luaXREaWN0KCkKb2xkX2NhdHMgPC0gdG9sb3dlcihuYW1lcyhzb3J0KHRhYmxlKHRyYWluJENhdGVnb3J5KSwgZGVjcmVhc2luZz1GKSkpCmZvciAoY2F0IGluIG9sZF9jYXRzKSB7CiAgb3JpZ2luX2NhdCA8LSBjYXQKICBpZiAoZ3JlcGwoIi8iLCBjYXQpKSB7CiAgICBjYXQgPC0gc3Ryc3BsaXQoY2F0LCAiLyIpCiAgICBmb3IgKHdvcmQgaW4gY2F0W1sxXV0pIHsKICAgICAgc3luX2xpc3QgPC0gc3lub255bXMod29yZCwgIk5PVU4iKQogICAgICBwYXR0ZXJuIDwtIHBhc3RlKHN5bl9saXN0LCBjb2xsYXBzZSA9ICJ8IikKICAgICAgdHJhaW4kS2V5d29yZFtncmVwbChwYXR0ZXJuLCB0cmFpbiREZXNjcmlwdCldIDwtIG9yaWdpbl9jYXQKICAgIH0KICB9IGVsc2UgewogICAgY2F0IDwtIHJlbW92ZVdvcmRzKGNhdCwgc3RvcHdvcmRzKCJlbiIpKQogICAgY2F0IDwtIHRyaW13cyhnc3ViKCIgKyIsICIgIiwgY2F0KSkgCiAgICBjYXQgPC0gc3Ryc3BsaXQoY2F0LCAiICIpCiAgICBmb3IgKHdvcmQgaW4gY2F0W1sxXV0pIHsKICAgICAgcGF0dGVyIDwtIHBhc3RlKHN5bm9ueW1zKHdvcmQsICJOT1VOIiksIGNvbGxhcHNlID0gInwiKQogICAgICB0cmFpbiRLZXl3b3JkW2dyZXBsKHBhdHRlcm4sIHRyYWluJERlc2NyaXB0KV0gPC0gb3JpZ2luX2NhdAogICAgfQogIH0KfQpgYGAKV29yZHMgd2l0aCB0b3AgZnJlcXVlbmN5LgpgYGB7cn0KIyBXb3JkcyBpbiBEZXNjcmlwdCB3aXRoIHRvcCBmcmVxdWVuY3kKZnJlcV93b3JkcyA8LSAodG9sb3dlcihmcmVxX3dvcmRzKSkKcmVtb3ZlIDwtIGMoIkZST00iLCAiV0lUSCIpCmZyZXFfd29yZHMgPC0gZnJlcV93b3Jkc1shZnJlcV93b3JkcyAlaW4lIHJlbW92ZV0KZm9yICh3b3JkIGluIGZyZXFfd29yZHMpIHsKICB0cmFpbiRLZXl3b3JkW2dyZXBsKHdvcmQsIHRyYWluJERlc2NyaXB0KV0gPC0gd29yZAp9CiNmcmVxX3dvcmRzCiNmcmVxX3dvcmRzX3N0ciA8LSBwYXN0ZShmcmVxX3dvcmRzLCBjb2xsYXBzZSA9ICJ8IikKI2ZyZXFfd29yZHNfc3RyCmBgYApMYXN0bHksIHBlcmZlY3QgbWF0Y2hlcy4KYGBge3J9CmxpYnJhcnkodG0pCmxpYnJhcnkoc3RyaW5ncikKIyBQcmVwcm9jZXNzIHRoZSBjYXRlZ29yaWVzIAp0cmFpbiREZXNjcmlwdCA8LSB0b2xvd2VyKHRyYWluJERlc2NyaXB0KQpvbGRfY2F0cyA8LSB0b2xvd2VyKG5hbWVzKHNvcnQodGFibGUodHJhaW4kQ2F0ZWdvcnkpLCBkZWNyZWFzaW5nPUYpKSkKZm9yIChjYXQgaW4gb2xkX2NhdHMpIHsKICBpZiAoZ3JlcGwoIi8iLCBjYXQpKSB7CiAgICBwYXR0ZXJuIDwtIGdzdWIoIi8iLCAifCIsIGNhdCkKICAgICNwcmludChjYXQpCiAgfSBlbHNlIHsKICAgIHBhdHRlcm4gPC0gcmVtb3ZlV29yZHMoY2F0LCBzdG9wd29yZHMoImVuIikpCiAgICBwYXR0ZXJuIDwtIHRyaW13cyhnc3ViKCIgKyIsICIgIiwgcGF0dGVybikpIAogIH0KICB0cmFpbiRLZXl3b3JkW2dyZXBsKHBhdHRlcm4sIHRyYWluJERlc2NyaXB0KV0gPC0gY2F0Cn0KYGBgCkZpbmFsbHkgd2UgbmVlZCB0byB0YWtlIGEgbG9vayBhdCB0aGUgcmVzb2x1dGlvbi4uLgpgYGB7cn0KcmVzX2RmIDwtIGRhdGEuZnJhbWUoUmVzb2x1dGlvbiA9IHRyYWluJFJlc29sdXRpb24sIENhdGVnb3J5ID0gdHJhaW4kQ2F0ZWdvcnkpCmcgPC0gZ2dwbG90KHJlc19kZiwgYWVzKFJlc29sdXRpb24pKQpnICsgZ2VvbV9iYXIoKSArIGdlb21fYmFyKGFlcyhmaWxsPUNhdGVnb3J5KSkgKyBnZ3RpdGxlKCJDcmltZSBSZXNvbHV0aW9ucyIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsaGp1c3Q9MSkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKyB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTUpKQpgYGAKYGBge3J9CmNvbG5hbWVzKHRyYWluKVt3aGljaChuYW1lcyh0cmFpbikgPT0gIktleXdvcmQiKV0gPC0gIktleXdvcmQiCnByb3AudGFibGUodGFibGUoaXMubmEodHJhaW4kS2V5d29yZCkpKQp0YWJsZSh0cmFpbiRLZXl3b3JkKQp1bmlxdWUodHJhaW4kS2V5d29yZCkKYGBgCk5lZWQgdG8gaW1wcm92ZS4uLlJlZHVjZSBUUlVFIHZhbHVlcy4uLgpgYGB7cn0KdGFibGUodHJhaW4kQWRkcmVzcykKYGBgCgo=